This notebook provides the plots for the article: Heyne, M., Derrick, D., and Al-Tamimi, J. (under review). “Native language influence on brass instrument performance: An application of generalized additive mixed models (GAMMs) to midsagittal ultrasound images of the tongue”. Frontiers Research Topic: Models and Theories of Speech Production. Ed. Adamantios Gafos & Pascal van Lieshout.

1 Loading packages

load_packages = c("readr","knitr","ggplot2","mgcv","itsadug","parallel","dplyr","rlist","plotly")
# dplyr, rlist, and plotly are required by the custom plotting functions
for(pkg in load_packages){
  eval(bquote(library(.(pkg))))
  if (paste0("package:", pkg) %in% search()){
    cat(paste0("Successfully loaded the ", pkg, " package.\n"))
  }else{
    install.packages(pkg)
    eval(bquote(library(.(pkg))))
    if (paste0("package:", pkg) %in% search()){
      cat(paste0("Successfully loaded the ", pkg, " package.\n"))
    }
  }
}
Successfully loaded the readr package.
Successfully loaded the knitr package.
Successfully loaded the ggplot2 package.
Successfully loaded the mgcv package.
Successfully loaded the itsadug package.
Successfully loaded the parallel package.
Successfully loaded the dplyr package.
Successfully loaded the rlist package.
Successfully loaded the plotly package.
rm(load_packages, pkg)
Sys.setenv('MAPBOX_TOKEN' = 'sk.eyJ1IjoiZGRlcnJpY2siLCJhIjoiY2p2MW1ndnNoMXczYTRkbXd6dzRuMTQ2aCJ9.UTai4wWcFFVaJAuOrAX7VQ')
# decide whether to save plots as PDF and jpg files using the Orca command line utility
save=FALSE
printPDF=FALSE

1.1 Loading custom plotting functions

1.1.1 plotly_model_outputs function (Matthias Heyne, 2019)

# plot multiple GAM model outputs
plotly_model_outputs <- function(model, changing_cond, changing_var, constant_cond1, constant_var1, values, constant_cond2=NULL, constant_var2=NULL, print=TRUE){
  if(length(constant_var1)>1 | length(constant_var2)>1){
    print("Error: Constant variables can only have length 1.")
  }else{
    if(!is.null(constant_cond2) && !is.null(constant_var2) && length(changing_var)==2){
      # works for models Notes.gam...
      cond_p1 = capture.output(cat(paste0("list(", changing_cond, "='", changing_var[1], "', ", constant_cond1, "='", constant_var1, "', ", constant_cond2, "='", constant_var2, "')")))
      p1=plot_smooth(x=get(model), view=values, cond = eval(parse(text=cond_p1)))
      cond_p2 = capture.output(cat(paste0("list(", changing_cond, "='", changing_var[2], "', ", constant_cond1, "='", constant_var1, "', ", constant_cond2, "='", constant_var2, "')")))
      p2=plot_smooth(x=get(model), view=values, cond = eval(parse(text=cond_p2)))
      
      # set Rho max to the max of the fit + half the difference between max of the fit and the upper limit
      # max_ul = max(p1$fv$ul, p2$fv$ul)
      # max_fit = max(p1$fv$fit, p2$fv$fit)
      # maximum = max_fit+((max_ul-max_fit)/2)
      maximum = max(p1$fv$ul, p2$fv$ul)
      
      # plot in polar coordinates
      p=plot_ly(type='scatterpolar', mode='lines') %>% 
        add_trace(theta=p1$fv$theta_uncut_z*180/pi, r=p1$fv$fit, line=list(color="blue", dash="dash", width=2.5), name=changing_var[1]) %>% 
        add_trace(theta=p1$fv$theta_uncut_z*180/pi, r=p1$fv$ul, line=list(color="blue", dash="dash", width=0.5), showlegend=FALSE) %>% 
        add_trace(theta=p1$fv$theta_uncut_z*180/pi, r=p1$fv$ll, line=list(color="blue", dash="dash", width=0.5), showlegend=FALSE) %>% 
        add_trace(theta=p2$fv$theta_uncut_z*180/pi, r=p2$fv$fit, line=list(color="red", width=2.5), name=changing_var[2]) %>% 
        add_trace(theta=p2$fv$theta_uncut_z*180/pi, r=p2$fv$ul, line=list(color="red", dash="dot", width=0.5), showlegend=FALSE) %>% 
        add_trace(theta=p2$fv$theta_uncut_z*180/pi, r=p2$fv$ll, line=list(color="red", dash="dot", width=0.5), showlegend=FALSE) %>%
        layout(polar=list(sector=c(20,160), radialaxis=list(angle=90, range=c(0,maximum)),
                          angularaxis=list(thetaunit='radians', direction="clockwise", rotation=0)), 
               title=paste0("GAM smooths @", constant_var1, " & ", constant_var2), 
               legend=list(orientation="h", xanchor="center", x=0.5,y=0.012))
      p
    }else if(is.null(constant_cond2) && is.null(constant_var2) && length(changing_var)==2){
      # no specific case yet
      cond_p1 = capture.output(cat(paste0("list(", changing_cond, "='", changing_var[1], "', ", constant_cond1, "='", constant_var1, "')")))
      p1=plot_smooth(x=get(model), view=values, cond = eval(parse(text=cond_p1)))
      cond_p2 = capture.output(cat(paste0("list(", changing_cond, "='", changing_var[2], "', ", constant_cond1, "='", constant_var1, "')")))
      p2=plot_smooth(x=get(model), view=values, cond = eval(parse(text=cond_p2)))
      
      # set Rho max to the max of the fit + half the difference between max of the fit and the upper limit
      # max_ul = max(p1$fv$ul, p2$fv$ul)
      # max_fit = max(p1$fv$fit, p2$fv$fit)
      # maximum = max_fit+((max_ul-max_fit)/2)
      maximum = max(p1$fv$ul, p2$fv$ul)
      
      # plot in polar coordinates
      p=plot_ly(type='scatterpolar', mode='lines') %>% 
        add_trace(theta=p1$fv$theta_uncut_z*180/pi, r=p1$fv$fit, line=list(color="blue", dash="dash", width=2.5), name=changing_var[1]) %>% 
        add_trace(theta=p1$fv$theta_uncut_z*180/pi, r=p1$fv$ul, line=list(color="blue", dash="dash", width=0.5), showlegend=FALSE) %>% 
        add_trace(theta=p1$fv$theta_uncut_z*180/pi, r=p1$fv$ll, line=list(color="blue", dash="dash", width=0.5), showlegend=FALSE) %>% 
        add_trace(theta=p2$fv$theta_uncut_z*180/pi, r=p2$fv$fit, line=list(color="red", width=2.5), name=changing_var[2]) %>% 
        add_trace(theta=p2$fv$theta_uncut_z*180/pi, r=p2$fv$ul, line=list(color="red", dash="dot", width=0.5), showlegend=FALSE) %>% 
        add_trace(theta=p2$fv$theta_uncut_z*180/pi, r=p2$fv$ll, line=list(color="red", dash="dot", width=0.5), showlegend=FALSE) %>%
        layout(polar=list(sector=c(20,160), radialaxis=list(angle=90, range=c(0,maximum)),
                          angularaxis=list(thetaunit='radians', direction="clockwise", rotation=0)), 
               title=paste0("GAM smooths @", constant_var1, " & ", constant_var2), 
               legend=list(orientation="h", xanchor="center", x=0.5,y=0.012))
      p
    }else if(is.null(constant_cond2) && is.null(constant_var2) && length(changing_var)>2){
      # works for models NZE.gam... or Tongan.gam...
      for (i in 1:length(changing_var)){
        if(changing_cond == constant_cond1){
          cond_p1 = capture.output(cat(paste0("list(", constant_cond1, "='", constant_var1, "')")))
          p1=plot_smooth(x=get(model), view=values, cond = eval(parse(text=cond_p1)))
          # exception for KIT (='\\\\') when not using IPA symbols
          if (changing_var[i]!="\\\\"){
            cond_p2 = capture.output(cat(paste0("list(", changing_cond, "='", changing_var[i], "')")))
            p2=plot_smooth(x=get(model), view=values, cond = eval(parse(text=cond_p2)))
          }else{
            p2=plot_smooth(x=get(model), view=values, cond = list(token.ord='\\\\'))
          }
          
          # set Rho max to the max of the fit + half the difference between max of the fit and the upper limit
          # max_ul = max(p1$fv$ul, p2$fv$ul)
          # max_fit = max(p1$fv$fit, p2$fv$fit)
          # maximum = max_fit+((max_ul-max_fit)/2)
          maximum = max(p1$fv$ul, p2$fv$ul)
          # plot in polar coordinates
          p=plot_ly(type='scatterpolar', mode='lines') %>% 
            add_trace(theta=p1$fv$theta_uncut_z*180/pi, r=p1$fv$fit, line=list(color="blue", dash="dash", width=2.5), name=constant_var1) %>% 
            add_trace(theta=p1$fv$theta_uncut_z*180/pi, r=p1$fv$ul, line=list(color="blue", dash="dash", width=0.5), showlegend=FALSE) %>% 
            add_trace(theta=p1$fv$theta_uncut_z*180/pi, r=p1$fv$ll, line=list(color="blue", dash="dash", width=0.5), showlegend=FALSE) %>% 
            add_trace(theta=p2$fv$theta_uncut_z*180/pi, r=p2$fv$fit, line=list(color="red", width=2.5), name=changing_var[i]) %>% 
            add_trace(theta=p2$fv$theta_uncut_z*180/pi, r=p2$fv$ul, line=list(color="red", dash="dot", width=0.5), showlegend=FALSE) %>% 
            add_trace(theta=p2$fv$theta_uncut_z*180/pi, r=p2$fv$ll, line=list(color="red", dash="dot", width=0.5), showlegend=FALSE) %>%
            layout(polar=list(sector=c(20,160), radialaxis=list(angle=90, range=c(0,maximum)),
                              angularaxis=list(thetaunit='radians', direction="clockwise", rotation=0)), 
                   title=paste0("GAM smooths ",constant_var1," vs ", changing_var[i]), 
                   legend=list(orientation="h", xanchor="center", x=0.5,y=0.012))
          Sys.sleep(0)
          print(p)
        }
      }
    }
  }
}

1.1.2 plotly_sig_diff_notes function (Matthias Heyne, 2019) -> with updated legend position

# plot smooths with shading to indicate significant differences (Matthias Heyne, 2019)
plotly_smooths_w_sig_diff <- function(model, condition, var1, var2, values, language, fileName, print=TRUE, save=TRUE){
  # specify path for saving plots
  # plot_folder = "saved_plots"
  # Sys.setenv(MAPBOX_TOKEN = 11122223333444)
  # get intervals of significant differences by running plot_diff
  # unfortunately setting plot=FALSE doesn't work as intervals of significant difference are not displayed!
  # hardcoded condition
  # output = capture.output(plot_diff(get(model), view=values, 
  #                                   comp=list(tokenPooled.ord=c(var1, var2))))
  # output = capture.output(plot_diff(get(model), view=values, comp=list(langNoteInt.ord=c(paste0("Tongan.", note, ".", intensity), paste0("NZE.", note, ".", intensity)))))
  names_smooths=list()
  if (condition=="tokenPooled.ord" && length(language)==1){
    output_comp = capture.output(cat(paste0("list(", condition, "=c(var1, var2))")))
    names_smooths[1]=var1
    names_smooths[2]=var2
    plot_title = paste0("GAM smooths ", language, " ", var1, " vs ", var2)
    # plot_filename = paste0(language, "_", var1, "_vs_", var2, "_from_", model)
  }else if (condition=="langNoteInt.ord" && length(language)==2){
    output_comp = capture.output(cat(paste0("list(", condition, "=c('", language[1], ".", var1, ".", var2, 
                                            "', '", language[2], ".", var1, ".", var2, "'))")))
    names_smooths[1]=paste0(language[1], ".", var1, ".", var2)
    names_smooths[2]=paste0(language[2], ".", var1, ".", var2)
    plot_title = paste0("GAM smooths ", language[1], ".", var1, ".", var2, " vs ", language[2], ".", var1, ".", var2)
    # plot_filename = paste0(language[1], ".", var1, ".", var2, "_vs_", language[2], ".", var1, ".", var2, "_from_", model)
  }else if (condition=="langNoteInt.ord" && length(language)==1 && length(var1)==2){
    output_comp = capture.output(cat(paste0("list(", condition, "=c('", language, ".", var1[1], ".", var2, 
                                            "', '", language, ".", var1[2], ".", var2, "'))")))
    names_smooths[1]=paste0(language, ".", var1[1], ".", var2)
    names_smooths[2]=paste0(language, ".", var1[2], ".", var2)
    plot_title = paste0("GAM smooths ", language, ".", var1[1], ".", var2, " vs ", language, ".", var1[2], ".", var2)
    # plot_filename = paste0(language, ".", var1[1], ".", var2, "_vs_", language, ".", var1[2], ".", var2, "_from_", model)
  }
  # output_comp = capture.output(cat(paste0("list(", condition, "=c(var1, var2))")))
  output = capture.output(plot_diff(get(model), view=values, comp=eval(parse(text=output_comp))))
  # no significant difference
  if ((length(language)==1 && length(var1)==1 && length(output)==7) | (length(language)==2 && length(output)==6) | 
    (length(language)==1 && length(var1)==2 && length(output)==6)){
    if (length(var1)==1){
      cat(paste0("Smooths for ", var1, " & ", var2, " are not significantly different.\n"))
      dat1 = NA
      assign(paste0("int_sig_diff_", var1, "_", var2), dat1, envir = .GlobalEnv)
    }else{
      cat(paste0("Smooths for ", var1[1], " & ", var1[2], " in ", language, " are not significantly different.\n"))
      dat1 = NA
      assign(paste0("int_sig_diff_", var1[1], "_", var1[2], "_", var2, "_", language), dat1, envir = .GlobalEnv)
    }
    rm(dat1, output)
    # run plot_smooth to grab data for polar plots
    if (condition=="tokenPooled.ord" && length(language)==1){
      cond_p1 = capture.output(cat(paste0("list(", condition, "=var1)")))
      cond_p2 = capture.output(cat(paste0("list(", condition, "=var2)")))
    }else if (condition=="langNoteInt.ord" && length(language)==2){
      cond_p1 = capture.output(cat(paste0("list(", condition, "='", language[1], ".", var1, ".", var2, 
                                          "', ", condition, "='", language[2], ".", var1, ".", var2, "')")))
      cond_p2 = capture.output(cat(paste0("list(", condition, "='", language[2], ".", var1, ".", var2, 
                                          "', ", condition, "='", language[1], ".", var1, ".", var2, "')")))
    }else if (condition=="langNoteInt.ord" && length(language)==1 && length(var1)==2){
      cond_p1 = capture.output(cat(paste0("list(", condition, "='", language, ".", var1[1], ".", var2, 
                                          "', ", condition, "='", language, ".", var1[2], ".", var2, "')")))
      cond_p2 = capture.output(cat(paste0("list(", condition, "='", language, ".", var1[2], ".", var2, 
                                          "', ", condition, "='", language, ".", var1[1], ".", var2, "')")))
    }
    p1 = plot_smooth(x=get(model), view=values, cond=eval(parse(text=cond_p1)), rm.ranef=TRUE)
    p2 = plot_smooth(x=get(model), view=values, cond=eval(parse(text=cond_p2)), rm.ranef=TRUE)
    # # old - hardcoded
    # p1 = plot_smooth(x=get(model), view=values, cond=list(tokenPooled.ord=var1, tokenPooled.ord=var2))
    # p2 = plot_smooth(x=get(model), view=values, cond=list(tokenPooled.ord=var2, tokenPooled.ord=var1))
    # set Rho max to the max of the fit + half the difference between max of the fit and the upper limit
    # maximum=max(p1$fv$fit, p2$fv$fit)+((max(p1$fv$ul, p2$fv$ul)-max(p1$fv$fit, p2$fv$fit))/2)
    maximum=max(p1$fv$ul, p2$fv$ul)
    
    # plot in polar coordinates
    p=plot_ly(type='scatterpolar', mode='lines') %>% 
      add_trace(theta=p1$fv$theta_uncut_z*180/pi, r=p1$fv$fit, line=list(color="blue", dash="dash", width=2.5), name=names_smooths[1]) %>% 
      add_trace(theta=p1$fv$theta_uncut_z*180/pi, r=p1$fv$ul, line=list(color="blue", dash="dash", width=0.5), showlegend=FALSE) %>% 
      add_trace(theta=p1$fv$theta_uncut_z*180/pi, r=p1$fv$ll, line=list(color="blue", dash="dash",  width=0.5), showlegend=FALSE) %>% 
      add_trace(theta=p2$fv$theta_uncut_z*180/pi, r=p2$fv$fit, line=list(color="red", width=2.5), name=names_smooths[2]) %>% 
      add_trace(theta=p2$fv$theta_uncut_z*180/pi, r=p2$fv$ul, line=list(color="red", dash="dot", width=0.5), showlegend=FALSE) %>% 
      add_trace(theta=p2$fv$theta_uncut_z*180/pi, r=p2$fv$ll, line=list(color="red", dash="dot", width=0.5), showlegend=FALSE) %>%
      layout(polar=list(sector=c(20,160), radialaxis=list(angle=90, range=c(0,maximum)),
                        angularaxis=list(thetaunit='radians', direction="clockwise", rotation=0)), 
             title=paste0("GAM smooths ", language, " ", var1, " vs ", var2), 
             legend=list(orientation="h", xanchor="center", x=0.5,y=0.012))
    Sys.sleep(0)
    print(p)
  # there are differences...
  }else{
    # grab intervals of significant differences from output
    if (length(language)==1 && length(var1)==1 && length(output)>=8){
    # if (length(language)==1 && length(output)>=8){
      sig_diff1 = c(as.double(unlist(strsplit(unlist(strsplit(output[8], " "))[1], "\t"))[2]), as.double(unlist(strsplit(output[8], " "))[3]))
    }else if ((length(language)==2 && length(output)>=7) | (length(language)==1 && length(var1)==2 && length(output)>=7)){
    # }else if (length(language)==2 && length(output)>=7){
      sig_diff1 = c(as.double(unlist(strsplit(unlist(strsplit(output[7], " "))[1], "\t"))[2]), as.double(unlist(strsplit(output[7], " "))[3]))
    }
    if (length(language)==1 && length(var1)==1 && length(output)>=9){
    # if (length(language)==1 && length(output)>=9){
      sig_diff2 = c(as.double(unlist(strsplit(unlist(strsplit(output[9], " "))[1], "\t"))[2]), as.double(unlist(strsplit(output[9], " "))[3]))
    }else if ((length(language)==2 && length(output)>=8) | (length(language)==1 && length(var1)==2 && length(output)>=8)){
    # }else if (length(language)==2 && length(output)>=8){
      sig_diff2 = c(as.double(unlist(strsplit(unlist(strsplit(output[8], " "))[1], "\t"))[2]), as.double(unlist(strsplit(output[8], " "))[3]))
    }
    if (length(language)==1 && length(var1)==1 && length(output)>=10){
    # if (length(language)==1 && length(output)>=10){
      sig_diff3 = c(as.double(unlist(strsplit(unlist(strsplit(output[10], " "))[1], "\t"))[2]), as.double(unlist(strsplit(output[10], " "))[3]))
    }else if ((length(language)==2 && length(output)>=9) | (length(language)==1 && length(var1)==2 && length(output)>=9)){
    # }else if (length(language)==2 && length(output)>=9){
      sig_diff3 = c(as.double(unlist(strsplit(unlist(strsplit(output[9], " "))[1], "\t"))[2]), as.double(unlist(strsplit(output[9], " "))[3]))
    }
    if (length(language)==1 && length(var1)==1 && length(output)>=11){
    # if (length(language)==1 && length(output)>=11){
      sig_diff4 = c(as.double(unlist(strsplit(unlist(strsplit(output[11], " "))[1], "\t"))[2]), as.double(unlist(strsplit(output[11], " "))[3]))
    }else if ((length(language)==2 && length(output)>=10) | (length(language)==1 && length(var1)==2 && length(output)>=10)){
    # }else if (length(language)==2 && length(output)>=10){
      sig_diff4 = c(as.double(unlist(strsplit(unlist(strsplit(output[10], " "))[1], "\t"))[2]), as.double(unlist(strsplit(output[10], " "))[3]))
    }
    
    # write intervals of significant difference to variable
    if ((length(language)==1 && length(var1)==1 && length(output)>=11) | ((length(language)==2 && length(output)>=10)) | 
        (length(language)==1 && length(var1)==2 && length(output)>=10)){
    # if ((length(language)==1 && length(output)>=11) | (length(language)==2 && length(output)>=10)){
      dat1 = c(sig_diff1, sig_diff2, sig_diff3, sig_diff4)
    }else if ((length(language)==1 && length(var1)==1 && length(output)>=10) | ((length(language)==2 && length(output)>=9)) | 
              (length(language)==1 && length(var1)==2 && length(output)>=9)){
    # }else if ((length(language)==1 && length(output)>=10) | (length(language)==2 && length(output)>=9)){
      dat1 = c(sig_diff1, sig_diff2, sig_diff3)
    }else if ((length(language)==1 && length(var1)==1 && length(output)>=9) | ((length(language)==2 && length(output)>=8)) | 
              (length(language)==1 && length(var1)==2 && length(output)>=8)){
    # }else if ((length(language)==1 && length(output)>=9) | (length(language)==2 && length(output)>=8)){
      dat1 = c(sig_diff1, sig_diff2)
    }else{
      dat1 = sig_diff1
    }
    # old
    # assign(paste0("int_sig_diff_", var1, "_", var2), dat1, envir = .GlobalEnv)
    if (length(var1)==1){
      assign(paste0("int_sig_diff_", var1, "_", var2), dat1, envir = .GlobalEnv)
    }else{
      assign(paste0("int_sig_diff_", var1[1], "_", var1[2], "_", var2, "_", language), dat1, envir = .GlobalEnv)
    }
    rm(dat1, output)
    # run plot_smooth to grab data for polar plots
    if (condition=="tokenPooled.ord" && length(language)==1){
      cond_p1 = capture.output(cat(paste0("list(", condition, "=var1)")))
      cond_p2 = capture.output(cat(paste0("list(", condition, "=var2)")))
    }else if (condition=="langNoteInt.ord" && length(language)==2){
      cond_p1 = capture.output(cat(paste0("list(", condition, "='", language[1], ".", var1, ".", var2, 
                                "', ", condition, "='", language[2], ".", var1, ".", var2, "')")))
      cond_p2 = capture.output(cat(paste0("list(", condition, "='", language[2], ".", var1, ".", var2, 
                                          "', ", condition, "='", language[1], ".", var1, ".", var2, "')")))
    }else if (condition=="langNoteInt.ord" && length(language)==1 && length(var1)==2){
      cond_p1 = capture.output(cat(paste0("list(", condition, "='", language, ".", var1[1], ".", var2, 
                                          "', ", condition, "='", language, ".", var1[2], ".", var2, "')")))
      cond_p2 = capture.output(cat(paste0("list(", condition, "='", language, ".", var1[2], ".", var2, 
                                          "', ", condition, "='", language, ".", var1[1], ".", var2, "')")))
    }
    p1 = plot_smooth(x=get(model), view=values, cond=eval(parse(text=cond_p1)), rm.ranef=TRUE)
    p2 = plot_smooth(x=get(model), view=values, cond=eval(parse(text=cond_p2)), rm.ranef=TRUE)
    # set Rho max to the max of the fit + half the difference between max of the fit and the upper limit
    # maximum=max(p1$fv$fit, p2$fv$fit)+((max(p1$fv$ul, p2$fv$ul)-max(p1$fv$fit, p2$fv$fit))/2)
    maximum=max(p1$fv$ul, p2$fv$ul)
    
    # plot in polar coordinates
    if (exists("sig_diff4")){
      p=plot_ly(type='scatterpolar', mode='lines') %>% 
        add_trace(theta=p1$fv$theta_uncut_z*180/pi, r=p1$fv$fit, line=list(color="blue", dash="dash", width=2.5), name=names_smooths[1]) %>% 
        add_trace(theta=p1$fv$theta_uncut_z*180/pi, r=p1$fv$ul, line=list(color="blue", dash="dash", width=0.5), showlegend=FALSE) %>% 
        add_trace(theta=p1$fv$theta_uncut_z*180/pi, r=p1$fv$ll, line=list(color="blue", dash="dash", width=0.5), showlegend=FALSE) %>% 
        add_trace(theta=p2$fv$theta_uncut_z*180/pi, r=p2$fv$fit, line=list(color="red", width=2.5), name=names_smooths[2]) %>% 
        add_trace(theta=p2$fv$theta_uncut_z*180/pi, r=p2$fv$ul, line=list(color="red", dash="dot", width=0.5), showlegend=FALSE) %>% 
        add_trace(theta=p2$fv$theta_uncut_z*180/pi, r=p2$fv$ll, line=list(color="red", dash="dot", width=0.5), showlegend=FALSE) %>%
        add_trace(theta=seq(sig_diff1[1]*180/pi, sig_diff1[2]*180/pi, length.out=20), 
                  r=c(0, rep(maximum, 18), 0), line=list(color="black", width=0.5), fill="toself", fillcolor=rgb(0,0,0,max=255,alpha=25), showlegend=FALSE) %>%
        add_trace(theta=seq(sig_diff2[1]*180/pi, sig_diff2[2]*180/pi, length.out=20), 
                  r=c(0, rep(maximum, 18), 0), line=list(color="black", width=0.5), fill="toself", fillcolor=rgb(0,0,0,max=255,alpha=25), showlegend=FALSE) %>%
        add_trace(theta=seq(sig_diff3[1]*180/pi, sig_diff3[2]*180/pi, length.out=20), 
                  r=c(0, rep(maximum, 18), 0), line=list(color="black", width=0.5), fill="toself", fillcolor=rgb(0,0,0,max=255,alpha=25), showlegend=FALSE) %>%
        add_trace(theta=seq(sig_diff4[1]*180/pi, sig_diff4[2]*180/pi, length.out=20), 
                  r=c(0, rep(maximum, 18), 0), line=list(color="black", width=0.5), fill="toself", fillcolor=rgb(0,0,0,max=255,alpha=25), showlegend=FALSE) %>%
        layout(polar=list(sector=c(20,160), radialaxis=list(angle=90, range=c(0,maximum)),
                          angularaxis=list(thetaunit='radians', direction="clockwise", rotation=0)), 
               title=plot_title, legend=list(orientation="h", xanchor="center", x=0.5, y=0.012))
      Sys.sleep(0)
      print(p)
    }else if (exists("sig_diff3")){
      p=plot_ly(type='scatterpolar', mode='lines') %>% 
        add_trace(theta=p1$fv$theta_uncut_z*180/pi, r=p1$fv$fit, line=list(color="blue", dash="dash", width=2.5), name=names_smooths[1]) %>% 
        add_trace(theta=p1$fv$theta_uncut_z*180/pi, r=p1$fv$ul, line=list(color="blue", dash="dash", width=0.5), showlegend=FALSE) %>% 
        add_trace(theta=p1$fv$theta_uncut_z*180/pi, r=p1$fv$ll, line=list(color="blue", dash="dash", width=0.5), showlegend=FALSE) %>% 
        add_trace(theta=p2$fv$theta_uncut_z*180/pi, r=p2$fv$fit, line=list(color="red", width=2.5), name=names_smooths[2]) %>% 
        add_trace(theta=p2$fv$theta_uncut_z*180/pi, r=p2$fv$ul, line=list(color="red", dash="dot", width=0.5), showlegend=FALSE) %>% 
        add_trace(theta=p2$fv$theta_uncut_z*180/pi, r=p2$fv$ll, line=list(color="red", dash="dot", width=0.5), showlegend=FALSE) %>%
        add_trace(theta=seq(sig_diff1[1]*180/pi, sig_diff1[2]*180/pi, length.out=20), 
                  r=c(0, rep(maximum, 18), 0), line=list(color="black", width=0.5), fill="toself", fillcolor=rgb(0,0,0,max=255,alpha=25), showlegend=FALSE) %>%
        add_trace(theta=seq(sig_diff2[1]*180/pi, sig_diff2[2]*180/pi, length.out=20), 
                  r=c(0, rep(maximum, 18), 0), line=list(color="black", width=0.5), fill="toself", fillcolor=rgb(0,0,0,max=255,alpha=25), showlegend=FALSE) %>%
        add_trace(theta=seq(sig_diff3[1]*180/pi, sig_diff3[2]*180/pi, length.out=20), 
                  r=c(0, rep(maximum, 18), 0), line=list(color="black", width=0.5), fill="toself", fillcolor=rgb(0,0,0,max=255,alpha=25), showlegend=FALSE) %>%
        layout(polar=list(sector=c(20,160), radialaxis=list(angle=90, range=c(0,maximum)),
                          angularaxis=list(thetaunit='radians', direction="clockwise", rotation=0)), 
               title=plot_title, legend=list(orientation="h", xanchor="center", x=0.5,y=0.012))
      Sys.sleep(0)
      print(p)
    }else if (exists("sig_diff2")){
      p=plot_ly(type='scatterpolar', mode='lines') %>% 
        add_trace(theta=p1$fv$theta_uncut_z*180/pi, r=p1$fv$fit, line=list(color="blue", dash="dash", width=2.5), name=names_smooths[1]) %>% 
        add_trace(theta=p1$fv$theta_uncut_z*180/pi, r=p1$fv$ul, line=list(color="blue", dash="dash", width=0.5), showlegend=FALSE) %>% 
        add_trace(theta=p1$fv$theta_uncut_z*180/pi, r=p1$fv$ll, line=list(color="blue", dash="dash", width=0.5), showlegend=FALSE) %>% 
        add_trace(theta=p2$fv$theta_uncut_z*180/pi, r=p2$fv$fit, line=list(color="red", width=2.5), name=names_smooths[2]) %>% 
        add_trace(theta=p2$fv$theta_uncut_z*180/pi, r=p2$fv$ul, line=list(color="red", dash="dot", width=0.5), showlegend=FALSE) %>% 
        add_trace(theta=p2$fv$theta_uncut_z*180/pi, r=p2$fv$ll, line=list(color="red", dash="dot", width=0.5), showlegend=FALSE) %>%
        add_trace(theta=seq(sig_diff1[1]*180/pi, sig_diff1[2]*180/pi, length.out=20), 
                  r=c(0, rep(maximum, 18), 0), line=list(color="black", width=0.5), fill="toself", fillcolor=rgb(0,0,0,max=255,alpha=25), showlegend=FALSE) %>%
        add_trace(theta=seq(sig_diff2[1]*180/pi, sig_diff2[2]*180/pi, length.out=20), 
                  r=c(0, rep(maximum, 18), 0), line=list(color="black", width=0.5), fill="toself", fillcolor=rgb(0,0,0,max=255,alpha=25), showlegend=FALSE) %>%
        layout(polar=list(sector=c(20,160), radialaxis=list(angle=90, range=c(0,maximum)),
                          angularaxis=list(thetaunit='radians', direction="clockwise", rotation=0)), 
               title=plot_title, legend=list(orientation="h", xanchor="center", x=0.5,y=0.012))
      Sys.sleep(0)
      print(p)
    }else{
      p=plot_ly(type='scatterpolar', mode='lines') %>% 
        add_trace(theta=p1$fv$theta_uncut_z*180/pi, r=p1$fv$fit, line=list(color="blue", dash="dash", width=2.5), name=names_smooths[1]) %>% 
        add_trace(theta=p1$fv$theta_uncut_z*180/pi, r=p1$fv$ul, line=list(color="blue", dash="dash", width=0.5), showlegend=FALSE) %>% 
        add_trace(theta=p1$fv$theta_uncut_z*180/pi, r=p1$fv$ll, line=list(color="blue", dash="dash", width=0.5), showlegend=FALSE) %>% 
        add_trace(theta=p2$fv$theta_uncut_z*180/pi, r=p2$fv$fit, line=list(color="red", width=2.5), name=names_smooths[2]) %>% 
        add_trace(theta=p2$fv$theta_uncut_z*180/pi, r=p2$fv$ul, line=list(color="red", dash="dot", width=0.5), showlegend=FALSE) %>% 
        add_trace(theta=p2$fv$theta_uncut_z*180/pi, r=p2$fv$ll, line=list(color="red", dash="dot", width=0.5), showlegend=FALSE) %>%
        add_trace(theta=seq(sig_diff1[1]*180/pi, sig_diff1[2]*180/pi, length.out=20), 
                  r=c(0, rep(maximum, 18), 0), line=list(color="black", width=0.5), fill="toself", fillcolor=rgb(0,0,0,max=255,alpha=25), showlegend=FALSE) %>%
        layout(polar=list(sector=c(20,160), radialaxis=list(angle=90, range=c(0,maximum)),
                          angularaxis=list(thetaunit='radians', direction="clockwise", rotation=0)), 
               title=plot_title, legend=list(orientation="h", xanchor="center", x=0.5,y=0.012))
      Sys.sleep(0)
      print(p)
    }
  }
  # orca should work with plotly 4.9.0 after loading the orca module before stating R and RStudio
  if(save==TRUE)
  {
    orca(p, paste(fileName,".pdf",sep=""),format="pdf")
    orca(p, paste(fileName,".pdf",sep=""),format="jpeg")
  }
}

2 Load final models

# load final model for H1
Notes.gam.AR.Mod2 = readRDS("updated_models/Notes.gam.AR.Mod2.rds")
# load final model for H1b
VAR.gam.AR.Mod2 = readRDS("updated_models/VAR.gam.AR.Mod2.rds")
# load final models for H2
NZE.gam.AR.Mod2 = readRDS("updated_models/NZE.gam.AR.Mod2.rds")
Tongan.gam.AR.Mod2 = readRDS("updated_models/Tongan.gam.AR.Mod2.rds")

3 Create paper plots

3.1 (new) Figure 4 H1 -> predict average values for note productions NZE vs Tongan

# create dfNotes
df <- read.csv("all_data_NZE_Tongan_w_context_checked_7_March_2019_not_cut_checked_27_Apr.csv", sep=',', stringsAsFactors = F)
df$X = NULL
df$tokenPooled <- factor(df$tokenPooled)
df$subject <- factor(df$subject)
df$sex <- factor(df$sex)
df$native_lg <- factor(df$native_lg)
df$playing_proficiency[df$playing_proficiency == "intermediate"] <- "amateur"
df$playing_proficiency <- factor(df$playing_proficiency, levels = c("amateur","semi-professional","professional"))
df$block <- factor(df$block)
df$point <- as.numeric(df$point)
df$note_intensity <- factor(df$note_intensity, levels = c("piano","mezzopiano","mezzoforte","forte"))
# remove fortissimo tokens
df = df[!(is.na(df$note_intensity) & df$activity=="music"),]
dfNotes <- subset(df,df$tokenPooled == "Bb2"|
                    df$tokenPooled == "Bb3"|
                    df$tokenPooled == "D4"|
                    df$tokenPooled == "F3"|
                    df$tokenPooled == "F4")
dfNotes$tokenPooled <- factor(dfNotes$tokenPooled, levels = c("Bb2","F3","Bb3","D4","F4"))
dfNotes <- subset(dfNotes,dfNotes$note_intensity == "forte"|
                    dfNotes$note_intensity == "mezzoforte"|
                    dfNotes$note_intensity == "mezzopiano"|
                    dfNotes$note_intensity == "piano")
dfNotes$note_intensity <- factor(dfNotes$note_intensity, levels = c("piano","mezzopiano","mezzoforte","forte"))
dfNotes$noteIntenInt <- interaction(dfNotes$tokenPooled, dfNotes$note_intensity)
dfNotes$langNoteInt <- interaction(dfNotes$native_lg, dfNotes$tokenPooled, dfNotes$note_intensity)
dfNotes$native_lg.ord <- as.ordered(dfNotes$native_lg)
contrasts(dfNotes$native_lg.ord) <- "contr.treatment"
dfNotes$tokenPooled.ord <- as.ordered(dfNotes$tokenPooled)
contrasts(dfNotes$tokenPooled.ord) <- "contr.treatment"
dfNotes$note_intensity.ord <- as.ordered(dfNotes$note_intensity)
contrasts(dfNotes$note_intensity.ord) <- "contr.treatment"
dfNotes$langNoteInt.ord <- as.ordered(dfNotes$langNoteInt)
contrasts(dfNotes$langNoteInt.ord) <- "contr.treatment"
dfNotes$start <- dfNotes$points==1
# make copy of dfNotes
dat1 = dfNotes
dat1$predicted_values = predict(Notes.gam.AR.Mod2)
# with SE -> takes very long!!!
# dat1$predicted_values = predict(Notes.gam.AR.Mod2, se.fit=TRUE)
# plot in polar coordinates using plotly
dat1_NZE = dat1[dat1$native_lg == "NZE",]
dat1_Tongan = dat1[dat1$native_lg == "Tongan",]
# estimate smooths using R's generic predict.smooth.spline function
smooth_NZE=list(theta=seq(min(dat1_NZE$theta_uncut_z)*180/pi, max(dat1_NZE$theta_uncut_z)*180/pi, length=100), r=predict(smooth.spline(dat1_NZE$theta_uncut_z, dat1_NZE$predicted_values),
 seq(min(dat1_NZE$theta_uncut_z), max(dat1_NZE$theta_uncut_z), length=100))$y, line=list(color="blue", dash="dash"))
smooth_Tongan=list(theta=seq(min(dat1_Tongan$theta_uncut_z)*180/pi, max(dat1_Tongan$theta_uncut_z)*180/pi, length=100), r=predict(smooth.spline(dat1_Tongan$theta_uncut_z, dat1_Tongan$predicted_values),
 seq(min(dat1_Tongan$theta_uncut_z), max(dat1_Tongan$theta_uncut_z), length=100))$y, line=list(color="red", dash=""))
# set Rho max to the max of the predicted_values + 5
max_predictions = max(max(smooth_NZE$r), max(smooth_Tongan$r))
maximum=max_predictions+5
rm(max_predictions)
p = plot_ly(type='scatterpolar', mode='lines') %>%
add_trace(theta=smooth_NZE$theta, r=smooth_NZE$r, line=list(color=smooth_NZE$line$color[[1]], width=2.5, dash=smooth_NZE$line$dash[[1]]), name="overall average of NZE notes") %>%
  add_trace(theta=smooth_Tongan$theta, r=smooth_Tongan$r, line=list(color=smooth_Tongan$line$color[[1]], width=2.5, dash=smooth_Tongan$line$dash[[1]]), name="overall average of Tongan notes") %>%
  layout(polar=list(sector=c(20,160), radialaxis=list(angle=90, range=c(0,maximum)), angularaxis=list(thetaunit='radians', direction="clockwise", rotation=0)), title="Overall average smooths for NZE vs Tongan note productions", legend=list(orientation="h", xanchor="center", x=0.5,y=0.012))
p

if(save==TRUE){
  orca(p, "Figure4.pdf",format="pdf")
  orca(p, "Figure4.jpg",format="jpeg")
}
rm(dat1, dat1_NZE, dat1_Tongan, maximum, smooth_NZE, smooth_Tongan)

3.2 Figure 5 (previously 4) -> H1

3.2.1 Bb2 forte

plotly_smooths_w_sig_diff(model="Notes.gam.AR.Mod2", condition="langNoteInt.ord", var1="Bb2", 
                          var2="forte", values="theta_uncut_z", 
                          language=c("NZE","Tongan"), fileName = "Figure5(a)", save=printPDF)
Summary:
    * langNoteInt.ord : factor; set to the value(s): NZE.Bb2.forte. 
    * theta_uncut_z : numeric predictor; with 30 values ranging from -2.648777 to -0.654831. 
    * subject : factor; set to the value(s): S3. (Might be canceled as random effect, check below.) 
    * noteIntenInt : factor; set to the value(s): F3.mezzoforte. 
    * NOTE : The following random effects columns are canceled: s(theta_uncut_z,subject):noteIntenIntBb2.piano,s(theta_uncut_z,subject):noteIntenIntF3.piano,s(theta_uncut_z,subject):noteIntenIntBb3.piano,s(theta_uncut_z,subject):noteIntenIntD4.piano,s(theta_uncut_z,subject):noteIntenIntF4.piano,s(theta_uncut_z,subject):noteIntenIntBb2.mezzopiano,s(theta_uncut_z,subject):noteIntenIntF3.mezzopiano,s(theta_uncut_z,subject):noteIntenIntBb3.mezzopiano,s(theta_uncut_z,subject):noteIntenIntD4.mezzopiano,s(theta_uncut_z,subject):noteIntenIntF4.mezzopiano,s(theta_uncut_z,subject):noteIntenIntBb2.mezzoforte,s(theta_uncut_z,subject):noteIntenIntF3.mezzoforte,s(theta_uncut_z,subject):noteIntenIntBb3.mezzoforte,s(theta_uncut_z,subject):noteIntenIntD4.mezzoforte,s(theta_uncut_z,subject):noteIntenIntF4.mezzoforte,s(theta_uncut_z,subject):noteIntenIntBb2.forte,s(theta_uncut_z,subject):noteIntenIntF3.forte,s(theta_uncut_z,subject):noteIntenIntBb3.forte,s(theta_uncut_z,subject):noteIntenIntD4.forte,s(theta_uncut_z,subject):noteIntenIntF4.forte
 

Summary:
    * langNoteInt.ord : factor; set to the value(s): Tongan.Bb2.forte. 
    * theta_uncut_z : numeric predictor; with 30 values ranging from -2.648777 to -0.654831. 
    * subject : factor; set to the value(s): S3. (Might be canceled as random effect, check below.) 
    * noteIntenInt : factor; set to the value(s): F3.mezzoforte. 
    * NOTE : The following random effects columns are canceled: s(theta_uncut_z,subject):noteIntenIntBb2.piano,s(theta_uncut_z,subject):noteIntenIntF3.piano,s(theta_uncut_z,subject):noteIntenIntBb3.piano,s(theta_uncut_z,subject):noteIntenIntD4.piano,s(theta_uncut_z,subject):noteIntenIntF4.piano,s(theta_uncut_z,subject):noteIntenIntBb2.mezzopiano,s(theta_uncut_z,subject):noteIntenIntF3.mezzopiano,s(theta_uncut_z,subject):noteIntenIntBb3.mezzopiano,s(theta_uncut_z,subject):noteIntenIntD4.mezzopiano,s(theta_uncut_z,subject):noteIntenIntF4.mezzopiano,s(theta_uncut_z,subject):noteIntenIntBb2.mezzoforte,s(theta_uncut_z,subject):noteIntenIntF3.mezzoforte,s(theta_uncut_z,subject):noteIntenIntBb3.mezzoforte,s(theta_uncut_z,subject):noteIntenIntD4.mezzoforte,s(theta_uncut_z,subject):noteIntenIntF4.mezzoforte,s(theta_uncut_z,subject):noteIntenIntBb2.forte,s(theta_uncut_z,subject):noteIntenIntF3.forte,s(theta_uncut_z,subject):noteIntenIntBb3.forte,s(theta_uncut_z,subject):noteIntenIntD4.forte,s(theta_uncut_z,subject):noteIntenIntF4.forte
 

3.2.2 F3 mezzoforte

plotly_smooths_w_sig_diff(model="Notes.gam.AR.Mod2", condition="langNoteInt.ord", var1="F3", 
                          var2="mezzoforte", values="theta_uncut_z",
                          language=c("NZE","Tongan"), ,fileName = "Figure5(b)",save=printPDF)
Summary:
    * langNoteInt.ord : factor; set to the value(s): NZE.F3.mezzoforte. 
    * theta_uncut_z : numeric predictor; with 30 values ranging from -2.648777 to -0.654831. 
    * subject : factor; set to the value(s): S3. (Might be canceled as random effect, check below.) 
    * noteIntenInt : factor; set to the value(s): F3.mezzoforte. 
    * NOTE : The following random effects columns are canceled: s(theta_uncut_z,subject):noteIntenIntBb2.piano,s(theta_uncut_z,subject):noteIntenIntF3.piano,s(theta_uncut_z,subject):noteIntenIntBb3.piano,s(theta_uncut_z,subject):noteIntenIntD4.piano,s(theta_uncut_z,subject):noteIntenIntF4.piano,s(theta_uncut_z,subject):noteIntenIntBb2.mezzopiano,s(theta_uncut_z,subject):noteIntenIntF3.mezzopiano,s(theta_uncut_z,subject):noteIntenIntBb3.mezzopiano,s(theta_uncut_z,subject):noteIntenIntD4.mezzopiano,s(theta_uncut_z,subject):noteIntenIntF4.mezzopiano,s(theta_uncut_z,subject):noteIntenIntBb2.mezzoforte,s(theta_uncut_z,subject):noteIntenIntF3.mezzoforte,s(theta_uncut_z,subject):noteIntenIntBb3.mezzoforte,s(theta_uncut_z,subject):noteIntenIntD4.mezzoforte,s(theta_uncut_z,subject):noteIntenIntF4.mezzoforte,s(theta_uncut_z,subject):noteIntenIntBb2.forte,s(theta_uncut_z,subject):noteIntenIntF3.forte,s(theta_uncut_z,subject):noteIntenIntBb3.forte,s(theta_uncut_z,subject):noteIntenIntD4.forte,s(theta_uncut_z,subject):noteIntenIntF4.forte
 

Summary:
    * langNoteInt.ord : factor; set to the value(s): Tongan.F3.mezzoforte. 
    * theta_uncut_z : numeric predictor; with 30 values ranging from -2.648777 to -0.654831. 
    * subject : factor; set to the value(s): S3. (Might be canceled as random effect, check below.) 
    * noteIntenInt : factor; set to the value(s): F3.mezzoforte. 
    * NOTE : The following random effects columns are canceled: s(theta_uncut_z,subject):noteIntenIntBb2.piano,s(theta_uncut_z,subject):noteIntenIntF3.piano,s(theta_uncut_z,subject):noteIntenIntBb3.piano,s(theta_uncut_z,subject):noteIntenIntD4.piano,s(theta_uncut_z,subject):noteIntenIntF4.piano,s(theta_uncut_z,subject):noteIntenIntBb2.mezzopiano,s(theta_uncut_z,subject):noteIntenIntF3.mezzopiano,s(theta_uncut_z,subject):noteIntenIntBb3.mezzopiano,s(theta_uncut_z,subject):noteIntenIntD4.mezzopiano,s(theta_uncut_z,subject):noteIntenIntF4.mezzopiano,s(theta_uncut_z,subject):noteIntenIntBb2.mezzoforte,s(theta_uncut_z,subject):noteIntenIntF3.mezzoforte,s(theta_uncut_z,subject):noteIntenIntBb3.mezzoforte,s(theta_uncut_z,subject):noteIntenIntD4.mezzoforte,s(theta_uncut_z,subject):noteIntenIntF4.mezzoforte,s(theta_uncut_z,subject):noteIntenIntBb2.forte,s(theta_uncut_z,subject):noteIntenIntF3.forte,s(theta_uncut_z,subject):noteIntenIntBb3.forte,s(theta_uncut_z,subject):noteIntenIntD4.forte,s(theta_uncut_z,subject):noteIntenIntF4.forte
 

3.2.3 Bb3 mezzoforte

plotly_smooths_w_sig_diff(model="Notes.gam.AR.Mod2", condition="langNoteInt.ord", var1="Bb3", 
                          var2="mezzoforte", values="theta_uncut_z", 
                          language=c("NZE","Tongan"),fileName = "Figure5(c)",save=printPDF)
Summary:
    * langNoteInt.ord : factor; set to the value(s): NZE.Bb3.mezzoforte. 
    * theta_uncut_z : numeric predictor; with 30 values ranging from -2.648777 to -0.654831. 
    * subject : factor; set to the value(s): S3. (Might be canceled as random effect, check below.) 
    * noteIntenInt : factor; set to the value(s): F3.mezzoforte. 
    * NOTE : The following random effects columns are canceled: s(theta_uncut_z,subject):noteIntenIntBb2.piano,s(theta_uncut_z,subject):noteIntenIntF3.piano,s(theta_uncut_z,subject):noteIntenIntBb3.piano,s(theta_uncut_z,subject):noteIntenIntD4.piano,s(theta_uncut_z,subject):noteIntenIntF4.piano,s(theta_uncut_z,subject):noteIntenIntBb2.mezzopiano,s(theta_uncut_z,subject):noteIntenIntF3.mezzopiano,s(theta_uncut_z,subject):noteIntenIntBb3.mezzopiano,s(theta_uncut_z,subject):noteIntenIntD4.mezzopiano,s(theta_uncut_z,subject):noteIntenIntF4.mezzopiano,s(theta_uncut_z,subject):noteIntenIntBb2.mezzoforte,s(theta_uncut_z,subject):noteIntenIntF3.mezzoforte,s(theta_uncut_z,subject):noteIntenIntBb3.mezzoforte,s(theta_uncut_z,subject):noteIntenIntD4.mezzoforte,s(theta_uncut_z,subject):noteIntenIntF4.mezzoforte,s(theta_uncut_z,subject):noteIntenIntBb2.forte,s(theta_uncut_z,subject):noteIntenIntF3.forte,s(theta_uncut_z,subject):noteIntenIntBb3.forte,s(theta_uncut_z,subject):noteIntenIntD4.forte,s(theta_uncut_z,subject):noteIntenIntF4.forte
 

Summary:
    * langNoteInt.ord : factor; set to the value(s): Tongan.Bb3.mezzoforte. 
    * theta_uncut_z : numeric predictor; with 30 values ranging from -2.648777 to -0.654831. 
    * subject : factor; set to the value(s): S3. (Might be canceled as random effect, check below.) 
    * noteIntenInt : factor; set to the value(s): F3.mezzoforte. 
    * NOTE : The following random effects columns are canceled: s(theta_uncut_z,subject):noteIntenIntBb2.piano,s(theta_uncut_z,subject):noteIntenIntF3.piano,s(theta_uncut_z,subject):noteIntenIntBb3.piano,s(theta_uncut_z,subject):noteIntenIntD4.piano,s(theta_uncut_z,subject):noteIntenIntF4.piano,s(theta_uncut_z,subject):noteIntenIntBb2.mezzopiano,s(theta_uncut_z,subject):noteIntenIntF3.mezzopiano,s(theta_uncut_z,subject):noteIntenIntBb3.mezzopiano,s(theta_uncut_z,subject):noteIntenIntD4.mezzopiano,s(theta_uncut_z,subject):noteIntenIntF4.mezzopiano,s(theta_uncut_z,subject):noteIntenIntBb2.mezzoforte,s(theta_uncut_z,subject):noteIntenIntF3.mezzoforte,s(theta_uncut_z,subject):noteIntenIntBb3.mezzoforte,s(theta_uncut_z,subject):noteIntenIntD4.mezzoforte,s(theta_uncut_z,subject):noteIntenIntF4.mezzoforte,s(theta_uncut_z,subject):noteIntenIntBb2.forte,s(theta_uncut_z,subject):noteIntenIntF3.forte,s(theta_uncut_z,subject):noteIntenIntBb3.forte,s(theta_uncut_z,subject):noteIntenIntD4.forte,s(theta_uncut_z,subject):noteIntenIntF4.forte
 

3.2.4 Intervals of significant difference 16 out of 19 comparisons

# read .csv file
sig_diffs = read.csv(file = "Notes.gam.AR.Mod2_intervals_of_significant_differences.csv", 
                     header=TRUE, row.names=1)
# Got rid of this plot!
# # visualize areas of overall difference
# p1=plot_ly(type='scatterpolar', mode='lines') %>%
#   add_trace(theta=seq(sig_diffs["17_out_of_19",1]*180/pi, sig_diffs["17_out_of_19",2]*180/pi, 
#                       length.out=20), r=c(0, rep(320, 18), 0), line=list(color="black", width=0.5), 
#             fill="toself", fillcolor=rgb(0,0,0,max=255,alpha=25), showlegend=FALSE) %>%
#   add_trace(theta=seq(sig_diffs["17_out_of_19",3]*180/pi, sig_diffs["17_out_of_19",4]*180/pi, 
#                       length.out=20), r=c(0, rep(320, 18), 0), line=list(color="black", width=0.5), 
#             fill="toself", fillcolor=rgb(0,0,0,max=255,alpha=25), showlegend=FALSE) %>% 
#   layout(polar=list(sector=c(20,160), radialaxis=list(angle=90, range=c(0,320)),
#                         angularaxis=list(thetaunit='radians', direction="clockwise", rotation=0)), 
#          title=paste0("Intervals of significant differences for 17 out of 19 comparisons"), 
#          legend=list(orientation="h", xanchor="center", x=0.5,y=0.012))
# Sys.sleep(0)
# print(p1)
p2=plot_ly(type='scatterpolar', mode='lines') %>%
  add_trace(theta=seq(sig_diffs["16_out_of_19",1]*180/pi, sig_diffs["16_out_of_19",2]*180/pi, 
                      length.out=20), r=c(0, rep(320, 18), 0), line=list(color="black", width=0.5), 
            fill="toself", fillcolor=rgb(0,0,0,max=255,alpha=25), showlegend=FALSE) %>%
  add_trace(theta=seq(sig_diffs["16_out_of_19",3]*180/pi, sig_diffs["16_out_of_19",4]*180/pi, 
                      length.out=20), r=c(0, rep(320, 18), 0), line=list(color="black", width=0.5), 
            fill="toself", fillcolor=rgb(0,0,0,max=255,alpha=25), showlegend=FALSE) %>% 
  layout(polar=list(sector=c(20,160), radialaxis=list(angle=90, range=c(0,270)),
                        angularaxis=list(thetaunit='radians', direction="clockwise", rotation=0)), 
         title=paste0("Intervals of significant differences for 16 out of 19 comparisons"), 
         legend=list(orientation="h", xanchor="center", x=0.5,y=0.012))
Sys.sleep(0)
print(p2)

NULL
if(printPDF==TRUE)
{
  orca(p2, "Figure5(d).pdf",format="pdf")
  orca(p2, "Figure5(d).jpg",format="jpeg")
}
rm(sig_diffs, p1, p2)

3.3 Figure 6 -> H1b

# df already loaded above
dfSummary <- group_by(df, subject, playing_proficiency, activity, native_lg, tokenPooled, theta_uncut_z_group = cut(theta_uncut_z,breaks=100)) %>% summarise(rhoVar = sd(rho_uncut_z,na.rm=TRUE))
dfSummary$theta_uncut_z = as.character(dfSummary$theta_uncut_z_group)
dfSummary$theta_uncut_z = gsub("\\[|\\]|\\(|\\)", "",dfSummary$theta_uncut_z)
dfSummary$theta_uncut_z = strsplit(dfSummary$theta_uncut_z,",")
dfSummary$theta_uncut_z2 = 1
for(i in c(1:nrow(dfSummary)))
{
  dfSummary$theta_uncut_z2[i] = mean(as.numeric(unlist(dfSummary$theta_uncut_z[i])))
}
dfSummary$theta_uncut_z=dfSummary$theta_uncut_z2
dfSummary$playing_proficiency.ord <- as.ordered(dfSummary$playing_proficiency)
contrasts(dfSummary$playing_proficiency.ord) <- "contr.treatment"
dfSummary$activity.ord <- as.ordered(dfSummary$activity)
contrasts(dfSummary$activity.ord) <- "contr.treatment"
dfSummary$langNoteInt <- interaction(dfSummary$native_lg, 
dfSummary$tokenPooled)
dfSummary$langNoteInt.ord <- as.ordered(dfSummary$langNoteInt)
contrasts(dfSummary$langNoteInt.ord) <- "contr.treatment"
dfSummary$native_lg.ord <- as.ordered(dfSummary$native_lg)
contrasts(dfSummary$native_lg.ord) <- "contr.treatment"
dfSummary$tokenPooled.ord <- as.ordered(dfSummary$tokenPooled)
contrasts(dfSummary$tokenPooled.ord) <- "contr.treatment"
dfSummary = na.omit(dfSummary)
#dfSummary$start <- dfSummary$theta_uncut_z==min(dfSummary$theta_uncut_z)
dfSummary$start = TRUE
for(i in unique(dfSummary$subject))
{
  dfSubject = subset(dfSummary,dfSummary$subject == i)
  for(j in unique(dfSubject$tokenPooled))
  {
    dfSummary$start[dfSummary$subject == i & dfSummary$tokenPooled == j] <- 
      dfSummary$theta_uncut_z[dfSummary$subject == i & dfSummary$tokenPooled == j] ==
      min(dfSummary$theta_uncut_z[dfSummary$subject == i & dfSummary$tokenPooled == j])
  }
}
# make copy of dfNotes
dat1 = dfSummary
dat1$predicted_values = predict(VAR.gam.AR.Mod2)
# plot in polar coordinates using plotly
dat1_NZE = dat1[dat1$native_lg == "NZE",]
dat1_Tongan = dat1[dat1$native_lg == "Tongan",]
# estimate smooths using R's generic predict.smooth.spline function
smooth_NZE=list(theta=seq(min(dat1_NZE$theta_uncut_z)*180/pi, max(dat1_NZE$theta_uncut_z)*180/pi, length=100), r=predict(smooth.spline(dat1_NZE$theta_uncut_z, dat1_NZE$predicted_values),
 seq(min(dat1_NZE$theta_uncut_z), max(dat1_NZE$theta_uncut_z), length=100))$y, line=list(color="blue", dash="dash"))
smooth_Tongan=list(theta=seq(min(dat1_Tongan$theta_uncut_z)*180/pi, max(dat1_Tongan$theta_uncut_z)*180/pi, length=100), r=predict(smooth.spline(dat1_Tongan$theta_uncut_z, dat1_Tongan$predicted_values),
 seq(min(dat1_Tongan$theta_uncut_z), max(dat1_Tongan$theta_uncut_z), length=100))$y, line=list(color="red", dash=""))
# set Rho max to the max of the predicted_values + 5
max_predictions = max(max(smooth_NZE$r), max(smooth_Tongan$r))
maximum=max_predictions+1
rm(max_predictions)
p = plot_ly(type='scatterpolar', mode='lines') %>%
add_trace(theta=smooth_NZE$theta, r=smooth_NZE$r, line=list(color=smooth_NZE$line$color[[1]], width=2.5, dash=smooth_NZE$line$dash[[1]]), name="overall average of NZE notes") %>%
  add_trace(theta=smooth_Tongan$theta, r=smooth_Tongan$r, line=list(color=smooth_Tongan$line$color[[1]], width=2.5, dash=smooth_Tongan$line$dash[[1]]), name="overall average of Tongan notes") %>%
  layout(polar=list(sector=c(20,160), radialaxis=list(angle=90, range=c(0,maximum)), angularaxis=list(thetaunit='radians', direction="clockwise", rotation=0)), title="Overall average smooths for NZE vs Tongan note productions", legend=list(orientation="h", xanchor="center", x=0.5,y=0.012))
p

if(printPDF==TRUE)
{
  orca(p, "Figure6.pdf",format="pdf")
  orca(p, "Figure6.jpg",format="jpeg")
}
rm(dat1, dat1_NZE, dat1_Tongan, maximum, smooth_NZE, smooth_Tongan)

3.4 Figure 7 -> H2 vowels and notes NZE

3.4.1 All NZE vowels

# define colors from PhD thesis
RED0 = (rgb(213,13,11, 255, maxColorValue=255))
BROWN0 = (rgb(123,73,55,255, maxColorValue=255))
PURPLE0 = (rgb(143,72,183,255, maxColorValue=255))
GRAY0 = (rgb(108,108,108,255, maxColorValue=255))
GREEN0 = (rgb(0,151,55,255, maxColorValue=255))
ORANGE0 = (rgb(255,123,0,255, maxColorValue=255))
PINK0 = (rgb(224,130,180,255, maxColorValue=255))
TEAL0 = (rgb(0,175,195,255, maxColorValue=255))
GOLD0 = (rgb(172,181,0,255, maxColorValue=255))
light_blue=rgb(0,117,220,255,maxColorValue=255)
black=rgb(25,25,25,255,maxColorValue=255)
pink=rgb(194,0,136,255,maxColorValue=255)
dark_blue=rgb(0,51,128,255,maxColorValue=255)
dark_red=rgb(153,0,0,255,maxColorValue=255)
# correct order
colors = c(ORANGE0, dark_blue, GREEN0, light_blue, PINK0, GOLD0, BROWN0, TEAL0, GRAY0, dark_red,
           RED0, PURPLE0, pink)
# run plot_smooth to grab values for fit, upper & lower bounds
p1=plot_smooth(x=NZE.gam.AR.Mod2, view="theta_uncut_z", cond=list(tokenPooled.ord="iː"), rm.ranef=TRUE)
Summary:
    * tokenPooled.ord : factor; set to the value(s): iː. 
    * theta_uncut_z : numeric predictor; with 30 values ranging from -2.627597 to -0.617214. 
    * subVowelInt : factor; set to the value(s): S3.ə. (Might be canceled as random effect, check below.) 
    * precSoundVowelInt : factor; set to the value(s): mezzoforte.F3. (Might be canceled as random effect, check below.) 
    * follSoundVowelInt : factor; set to the value(s): coronals.ə. (Might be canceled as random effect, check below.) 
    * NOTE : The following random effects columns are canceled: s(theta_uncut_z,subVowelInt),s(theta_uncut_z,precSoundVowelInt),s(theta_uncut_z,follSoundVowelInt)
 

p2=plot_smooth(x=NZE.gam.AR.Mod2, view="theta_uncut_z", cond=list(tokenPooled.ord="e"), rm.ranef=TRUE)
Summary:
    * tokenPooled.ord : factor; set to the value(s): e. 
    * theta_uncut_z : numeric predictor; with 30 values ranging from -2.627597 to -0.617214. 
    * subVowelInt : factor; set to the value(s): S3.ə. (Might be canceled as random effect, check below.) 
    * precSoundVowelInt : factor; set to the value(s): mezzoforte.F3. (Might be canceled as random effect, check below.) 
    * follSoundVowelInt : factor; set to the value(s): coronals.ə. (Might be canceled as random effect, check below.) 
    * NOTE : The following random effects columns are canceled: s(theta_uncut_z,subVowelInt),s(theta_uncut_z,precSoundVowelInt),s(theta_uncut_z,follSoundVowelInt)
 

p3=plot_smooth(x=NZE.gam.AR.Mod2, view="theta_uncut_z", cond=list(tokenPooled.ord="ʉː"), rm.ranef=TRUE)
Summary:
    * tokenPooled.ord : factor; set to the value(s): ʉː. 
    * theta_uncut_z : numeric predictor; with 30 values ranging from -2.627597 to -0.617214. 
    * subVowelInt : factor; set to the value(s): S3.ə. (Might be canceled as random effect, check below.) 
    * precSoundVowelInt : factor; set to the value(s): mezzoforte.F3. (Might be canceled as random effect, check below.) 
    * follSoundVowelInt : factor; set to the value(s): coronals.ə. (Might be canceled as random effect, check below.) 
    * NOTE : The following random effects columns are canceled: s(theta_uncut_z,subVowelInt),s(theta_uncut_z,precSoundVowelInt),s(theta_uncut_z,follSoundVowelInt)
 

p4=plot_smooth(x=NZE.gam.AR.Mod2, view="theta_uncut_z", cond=list(tokenPooled.ord="ɛ"), rm.ranef=TRUE)
Summary:
    * tokenPooled.ord : factor; set to the value(s): ɛ. 
    * theta_uncut_z : numeric predictor; with 30 values ranging from -2.627597 to -0.617214. 
    * subVowelInt : factor; set to the value(s): S3.ə. (Might be canceled as random effect, check below.) 
    * precSoundVowelInt : factor; set to the value(s): mezzoforte.F3. (Might be canceled as random effect, check below.) 
    * follSoundVowelInt : factor; set to the value(s): coronals.ə. (Might be canceled as random effect, check below.) 
    * NOTE : The following random effects columns are canceled: s(theta_uncut_z,subVowelInt),s(theta_uncut_z,precSoundVowelInt),s(theta_uncut_z,follSoundVowelInt)
 

p5=plot_smooth(x=NZE.gam.AR.Mod2, view="theta_uncut_z", cond=list(tokenPooled.ord="ɵː"), rm.ranef=TRUE)
Summary:
    * tokenPooled.ord : factor; set to the value(s): ɵː. 
    * theta_uncut_z : numeric predictor; with 30 values ranging from -2.627597 to -0.617214. 
    * subVowelInt : factor; set to the value(s): S3.ə. (Might be canceled as random effect, check below.) 
    * precSoundVowelInt : factor; set to the value(s): mezzoforte.F3. (Might be canceled as random effect, check below.) 
    * follSoundVowelInt : factor; set to the value(s): coronals.ə. (Might be canceled as random effect, check below.) 
    * NOTE : The following random effects columns are canceled: s(theta_uncut_z,subVowelInt),s(theta_uncut_z,precSoundVowelInt),s(theta_uncut_z,follSoundVowelInt)
 

p6=plot_smooth(x=NZE.gam.AR.Mod2, view="theta_uncut_z", cond=list(tokenPooled.ord="ɘ"), rm.ranef=TRUE)
Summary:
    * tokenPooled.ord : factor; set to the value(s): ɘ. 
    * theta_uncut_z : numeric predictor; with 30 values ranging from -2.627597 to -0.617214. 
    * subVowelInt : factor; set to the value(s): S3.ə. (Might be canceled as random effect, check below.) 
    * precSoundVowelInt : factor; set to the value(s): mezzoforte.F3. (Might be canceled as random effect, check below.) 
    * follSoundVowelInt : factor; set to the value(s): coronals.ə. (Might be canceled as random effect, check below.) 
    * NOTE : The following random effects columns are canceled: s(theta_uncut_z,subVowelInt),s(theta_uncut_z,precSoundVowelInt),s(theta_uncut_z,follSoundVowelInt)
 

p7=plot_smooth(x=NZE.gam.AR.Mod2, view="theta_uncut_z", cond=list(tokenPooled.ord="ə"), rm.ranef=TRUE)
Summary:
    * tokenPooled.ord : factor; set to the value(s): ə. 
    * theta_uncut_z : numeric predictor; with 30 values ranging from -2.627597 to -0.617214. 
    * subVowelInt : factor; set to the value(s): S3.ə. (Might be canceled as random effect, check below.) 
    * precSoundVowelInt : factor; set to the value(s): mezzoforte.F3. (Might be canceled as random effect, check below.) 
    * follSoundVowelInt : factor; set to the value(s): coronals.ə. (Might be canceled as random effect, check below.) 
    * NOTE : The following random effects columns are canceled: s(theta_uncut_z,subVowelInt),s(theta_uncut_z,precSoundVowelInt),s(theta_uncut_z,follSoundVowelInt)
 

p8=plot_smooth(x=NZE.gam.AR.Mod2, view="theta_uncut_z", cond=list(tokenPooled.ord="ʊ"), rm.ranef=TRUE)
Summary:
    * tokenPooled.ord : factor; set to the value(s): ʊ. 
    * theta_uncut_z : numeric predictor; with 30 values ranging from -2.627597 to -0.617214. 
    * subVowelInt : factor; set to the value(s): S3.ə. (Might be canceled as random effect, check below.) 
    * precSoundVowelInt : factor; set to the value(s): mezzoforte.F3. (Might be canceled as random effect, check below.) 
    * follSoundVowelInt : factor; set to the value(s): coronals.ə. (Might be canceled as random effect, check below.) 
    * NOTE : The following random effects columns are canceled: s(theta_uncut_z,subVowelInt),s(theta_uncut_z,precSoundVowelInt),s(theta_uncut_z,follSoundVowelInt)
 

p9=plot_smooth(x=NZE.gam.AR.Mod2, view="theta_uncut_z", cond=list(tokenPooled.ord="ə#"), rm.ranef=TRUE)
Summary:
    * tokenPooled.ord : factor; set to the value(s): ə#. 
    * theta_uncut_z : numeric predictor; with 30 values ranging from -2.627597 to -0.617214. 
    * subVowelInt : factor; set to the value(s): S3.ə. (Might be canceled as random effect, check below.) 
    * precSoundVowelInt : factor; set to the value(s): mezzoforte.F3. (Might be canceled as random effect, check below.) 
    * follSoundVowelInt : factor; set to the value(s): coronals.ə. (Might be canceled as random effect, check below.) 
    * NOTE : The following random effects columns are canceled: s(theta_uncut_z,subVowelInt),s(theta_uncut_z,precSoundVowelInt),s(theta_uncut_z,follSoundVowelInt)
 

p10=plot_smooth(x=NZE.gam.AR.Mod2, view="theta_uncut_z", cond=list(tokenPooled.ord="ɐ"), rm.ranef=TRUE)
Summary:
    * tokenPooled.ord : factor; set to the value(s): ɐ. 
    * theta_uncut_z : numeric predictor; with 30 values ranging from -2.627597 to -0.617214. 
    * subVowelInt : factor; set to the value(s): S3.ə. (Might be canceled as random effect, check below.) 
    * precSoundVowelInt : factor; set to the value(s): mezzoforte.F3. (Might be canceled as random effect, check below.) 
    * follSoundVowelInt : factor; set to the value(s): coronals.ə. (Might be canceled as random effect, check below.) 
    * NOTE : The following random effects columns are canceled: s(theta_uncut_z,subVowelInt),s(theta_uncut_z,precSoundVowelInt),s(theta_uncut_z,follSoundVowelInt)
 

p11=plot_smooth(x=NZE.gam.AR.Mod2, view="theta_uncut_z", cond=list(tokenPooled.ord="ɐː"), rm.ranef=TRUE)
Summary:
    * tokenPooled.ord : factor; set to the value(s): ɐː. 
    * theta_uncut_z : numeric predictor; with 30 values ranging from -2.627597 to -0.617214. 
    * subVowelInt : factor; set to the value(s): S3.ə. (Might be canceled as random effect, check below.) 
    * precSoundVowelInt : factor; set to the value(s): mezzoforte.F3. (Might be canceled as random effect, check below.) 
    * follSoundVowelInt : factor; set to the value(s): coronals.ə. (Might be canceled as random effect, check below.) 
    * NOTE : The following random effects columns are canceled: s(theta_uncut_z,subVowelInt),s(theta_uncut_z,precSoundVowelInt),s(theta_uncut_z,follSoundVowelInt)
 

p12=plot_smooth(x=NZE.gam.AR.Mod2, view="theta_uncut_z", cond=list(tokenPooled.ord="ɒ"), rm.ranef=TRUE)
Summary:
    * tokenPooled.ord : factor; set to the value(s): ɒ. 
    * theta_uncut_z : numeric predictor; with 30 values ranging from -2.627597 to -0.617214. 
    * subVowelInt : factor; set to the value(s): S3.ə. (Might be canceled as random effect, check below.) 
    * precSoundVowelInt : factor; set to the value(s): mezzoforte.F3. (Might be canceled as random effect, check below.) 
    * follSoundVowelInt : factor; set to the value(s): coronals.ə. (Might be canceled as random effect, check below.) 
    * NOTE : The following random effects columns are canceled: s(theta_uncut_z,subVowelInt),s(theta_uncut_z,precSoundVowelInt),s(theta_uncut_z,follSoundVowelInt)
 

p13=plot_smooth(x=NZE.gam.AR.Mod2, view="theta_uncut_z", cond=list(tokenPooled.ord="oː"), rm.ranef=TRUE)
Summary:
    * tokenPooled.ord : factor; set to the value(s): oː. 
    * theta_uncut_z : numeric predictor; with 30 values ranging from -2.627597 to -0.617214. 
    * subVowelInt : factor; set to the value(s): S3.ə. (Might be canceled as random effect, check below.) 
    * precSoundVowelInt : factor; set to the value(s): mezzoforte.F3. (Might be canceled as random effect, check below.) 
    * follSoundVowelInt : factor; set to the value(s): coronals.ə. (Might be canceled as random effect, check below.) 
    * NOTE : The following random effects columns are canceled: s(theta_uncut_z,subVowelInt),s(theta_uncut_z,precSoundVowelInt),s(theta_uncut_z,follSoundVowelInt)
 

smooth_names=c("FLEECE /iː/","DRESS /e/","GOOSE /ʉː/","TRAP /ɛ/","NURSE /ɵː/","KIT /ɘ/",
               "non-final schwa /ə/","FOOT /ʊ/","final schwa /ə#/","STRUT /ɐ/","START /ɐː/",
               "LOT /ɒ/","THOUGHT /oː/")
# # set Rho max to the max of the fit + half the difference between max of the fit and the upper limit
# max_ul = max(p1$fv$ul, p2$fv$ul, p3$fv$ul, p4$fv$ul, p5$fv$ul, p6$fv$ul, p7$fv$ul, p8$fv$ul, p9$fv$ul, p10$fv$ul, p11$fv$ul, p12$fv$ul, p13$fv$ul)
# max_fit = max(p1$fv$fit, p2$fv$fit, p3$fv$fit, p4$fv$fit, p5$fv$fit, p6$fv$fit, p7$fv$fit, p8$fv$fit, p9$fv$fit, p10$fv$fit, p11$fv$fit, p12$fv$fit, p13$fv$fit)
# maximum=max_fit+((max_ul-max_fit)/2)
# rm(max_ul, max_fit)
# 
# # plot in polar coordinates with confidence bounds
# plot1=plot_ly(type='scatterpolar', mode='lines') %>%
#   add_trace(theta=p1$fv$theta_uncut_z*180/pi, r=p1$fv$fit, line=list(color=colors[1], dash="dash", width=2.5), name=smooth_names[1]) %>%
#   add_trace(theta=p1$fv$theta_uncut_z*180/pi, r=p1$fv$ul, line=list(color=colors[1], dash="dash", width=0.5), showlegend=FALSE) %>%
#   add_trace(theta=p1$fv$theta_uncut_z*180/pi, r=p1$fv$ll, line=list(color=colors[1], dash="dash", width=0.5), showlegend=FALSE) %>%
#   add_trace(theta=p2$fv$theta_uncut_z*180/pi, r=p2$fv$fit, line=list(color=colors[2], width=2.5),
#             name=smooth_names[2]) %>%
#   add_trace(theta=p2$fv$theta_uncut_z*180/pi, r=p2$fv$ul, line=list(color=colors[2], dash="dot", width=0.5), showlegend=FALSE) %>%
#   add_trace(theta=p2$fv$theta_uncut_z*180/pi, r=p2$fv$ll, line=list(color=colors[2], dash="dot", width=0.5), showlegend=FALSE) %>%
#   add_trace(theta=p3$fv$theta_uncut_z*180/pi, r=p3$fv$fit, line=list(color=colors[3], width=2.5),
#             name=smooth_names[3]) %>%
#   add_trace(theta=p3$fv$theta_uncut_z*180/pi, r=p3$fv$ul, line=list(color=colors[3], dash="dot", width=0.5), showlegend=FALSE) %>%
#   add_trace(theta=p3$fv$theta_uncut_z*180/pi, r=p3$fv$ll, line=list(color=colors[3], dash="dot", width=0.5), showlegend=FALSE) %>%
#   add_trace(theta=p4$fv$theta_uncut_z*180/pi, r=p4$fv$fit, line=list(color=colors[4], dash="dash", width=2.5), name=smooth_names[4]) %>%
#   add_trace(theta=p4$fv$theta_uncut_z*180/pi, r=p4$fv$ul, line=list(color=colors[4], dash="dash", width=0.5), showlegend=FALSE) %>%
#   add_trace(theta=p4$fv$theta_uncut_z*180/pi, r=p4$fv$ll, line=list(color=colors[4], dash="dash", width=0.5), showlegend=FALSE) %>%
#   add_trace(theta=p5$fv$theta_uncut_z*180/pi, r=p5$fv$fit, line=list(color=colors[5], width=2.5),
#             name=smooth_names[5]) %>%
#   add_trace(theta=p5$fv$theta_uncut_z*180/pi, r=p5$fv$ul, line=list(color=colors[5], dash="dot", width=0.5), showlegend=FALSE) %>%
#   add_trace(theta=p5$fv$theta_uncut_z*180/pi, r=p5$fv$ll, line=list(color=colors[5], dash="dot", width=0.5), showlegend=FALSE) %>%
#   add_trace(theta=p6$fv$theta_uncut_z*180/pi, r=p6$fv$fit, line=list(color=colors[6], dash="dash", width=2.5), name=smooth_names[6]) %>%
#   add_trace(theta=p6$fv$theta_uncut_z*180/pi, r=p6$fv$ul, line=list(color=colors[6], dash="dash", width=0.5), showlegend=FALSE) %>%
#   add_trace(theta=p6$fv$theta_uncut_z*180/pi, r=p6$fv$ll, line=list(color=colors[6], dash="dash", width=0.5), showlegend=FALSE) %>%
#   add_trace(theta=p7$fv$theta_uncut_z*180/pi, r=p7$fv$fit, line=list(color=colors[7], width=2.5),
#             name=smooth_names[7]) %>%
#   add_trace(theta=p7$fv$theta_uncut_z*180/pi, r=p7$fv$ul, line=list(color=colors[7], dash="dot", width=0.5), showlegend=FALSE) %>%
#   add_trace(theta=p7$fv$theta_uncut_z*180/pi, r=p7$fv$ll, line=list(color=colors[7], dash="dot", width=0.5), showlegend=FALSE) %>%
#   add_trace(theta=p8$fv$theta_uncut_z*180/pi, r=p8$fv$fit, line=list(color=colors[8], dash="dash", width=2.5), name=smooth_names[8]) %>%
#   add_trace(theta=p8$fv$theta_uncut_z*180/pi, r=p8$fv$ul, line=list(color=colors[8], dash="dash", width=0.5), showlegend=FALSE) %>%
#   add_trace(theta=p8$fv$theta_uncut_z*180/pi, r=p8$fv$ll, line=list(color=colors[8], dash="dash", width=0.5), showlegend=FALSE) %>%
#   add_trace(theta=p9$fv$theta_uncut_z*180/pi, r=p9$fv$fit, line=list(color=colors[9], width=2.5),
#             name=smooth_names[9]) %>%
#   add_trace(theta=p9$fv$theta_uncut_z*180/pi, r=p9$fv$ul, line=list(color=colors[9], dash="dot", width=0.5), showlegend=FALSE) %>%
#   add_trace(theta=p9$fv$theta_uncut_z*180/pi, r=p9$fv$ll, line=list(color=colors[9], dash="dot", width=0.5), showlegend=FALSE) %>%
#   add_trace(theta=p10$fv$theta_uncut_z*180/pi, r=p10$fv$fit, line=list(color=colors[10], width=2.5),
#             name=smooth_names[10]) %>%
#   add_trace(theta=p10$fv$theta_uncut_z*180/pi, r=p10$fv$ul, line=list(color=colors[10], dash="dot", width=0.5), showlegend=FALSE) %>%
#   add_trace(theta=p10$fv$theta_uncut_z*180/pi, r=p10$fv$ll, line=list(color=colors[10], dash="dot", width=0.5), showlegend=FALSE) %>%
#   add_trace(theta=p11$fv$theta_uncut_z*180/pi, r=p11$fv$fit, line=list(color=colors[11], width=2.5),
#             name=smooth_names[11]) %>%
#   add_trace(theta=p11$fv$theta_uncut_z*180/pi, r=p11$fv$ul, line=list(color=colors[11], dash="dot", width=0.5), showlegend=FALSE) %>%
#   add_trace(theta=p11$fv$theta_uncut_z*180/pi, r=p11$fv$ll, line=list(color=colors[11], dash="dot", width=0.5), showlegend=FALSE) %>%
#   add_trace(theta=p12$fv$theta_uncut_z*180/pi, r=p12$fv$fit, line=list(color=colors[12], dash="dash", width=2.5), name=smooth_names[12]) %>%
#   add_trace(theta=p12$fv$theta_uncut_z*180/pi, r=p12$fv$ul, line=list(color=colors[12], dash="dash", width=0.5), showlegend=FALSE) %>%
#   add_trace(theta=p12$fv$theta_uncut_z*180/pi, r=p12$fv$ll, line=list(color=colors[12], dash="dash", width=0.5), showlegend=FALSE) %>%
#   add_trace(theta=p13$fv$theta_uncut_z*180/pi, r=p13$fv$fit, line=list(color=colors[13], width=2.5),
#             name=smooth_names[13]) %>%
#   add_trace(theta=p13$fv$theta_uncut_z*180/pi, r=p13$fv$ul, line=list(color=colors[13], dash="dot", width=0.5), showlegend=FALSE) %>%
#   add_trace(theta=p13$fv$theta_uncut_z*180/pi, r=p13$fv$ll, line=list(color=colors[13], dash="dot", width=0.5), showlegend=FALSE) %>%
#   layout(polar=list(sector=c(20,160), radialaxis=list(angle=90, range=c(0,maximum)),
#                     angularaxis=list(thetaunit='radians', direction="clockwise", rotation=0)),
#          title="All vowels produced by NZE speakers")
# plot1
# set Rho max to the max of the fit + 5
max_fit = max(p1$fv$fit, p2$fv$fit, p3$fv$fit, p4$fv$fit, p5$fv$fit, p6$fv$fit, p7$fv$fit, p8$fv$fit, p9$fv$fit, p10$fv$fit, p11$fv$fit, p12$fv$fit, p13$fv$fit)
maximum=max_fit+5
rm(max_fit)
# plot in polar coordinates without confidence bounds
plot2=plot_ly(type='scatterpolar', mode='lines') %>%
  add_trace(theta=p1$fv$theta_uncut_z*180/pi, r=p1$fv$fit, line=list(color=colors[1], dash="dash", width=2.5), name=smooth_names[1]) %>%
  add_trace(theta=p2$fv$theta_uncut_z*180/pi, r=p2$fv$fit, line=list(color=colors[2], width=2.5),
            name=smooth_names[2]) %>%
  add_trace(theta=p3$fv$theta_uncut_z*180/pi, r=p3$fv$fit, line=list(color=colors[3], width=2.5),
            name=smooth_names[3]) %>%
  add_trace(theta=p4$fv$theta_uncut_z*180/pi, r=p4$fv$fit, line=list(color=colors[4], dash="dash", width=2.5), name=smooth_names[4]) %>%
  add_trace(theta=p5$fv$theta_uncut_z*180/pi, r=p5$fv$fit, line=list(color=colors[5], width=2.5),
            name=smooth_names[5]) %>%
  add_trace(theta=p6$fv$theta_uncut_z*180/pi, r=p6$fv$fit, line=list(color=colors[6], dash="dash", width=2.5), name=smooth_names[6]) %>%
  add_trace(theta=p7$fv$theta_uncut_z*180/pi, r=p7$fv$fit, line=list(color=colors[7], width=2.5),
            name=smooth_names[7]) %>%
  add_trace(theta=p8$fv$theta_uncut_z*180/pi, r=p8$fv$fit, line=list(color=colors[8], dash="dash", width=2.5), name=smooth_names[8]) %>%
  add_trace(theta=p9$fv$theta_uncut_z*180/pi, r=p9$fv$fit, line=list(color=colors[9], width=2.5),
            name=smooth_names[9]) %>%
  add_trace(theta=p10$fv$theta_uncut_z*180/pi, r=p10$fv$fit, line=list(color=colors[10], width=2.5),
            name=smooth_names[10]) %>%
  add_trace(theta=p11$fv$theta_uncut_z*180/pi, r=p11$fv$fit, line=list(color=colors[11], width=2.5),
            name=smooth_names[11]) %>%
  add_trace(theta=p12$fv$theta_uncut_z*180/pi, r=p12$fv$fit, line=list(color=colors[12], dash="dash", width=2.5), name=smooth_names[12]) %>%
  add_trace(theta=p13$fv$theta_uncut_z*180/pi, r=p13$fv$fit, line=list(color=colors[13], width=2.5),
            name=smooth_names[13]) %>%
  layout(polar=list(sector=c(20,160), radialaxis=list(angle=90, range=c(0,maximum)),
                    angularaxis=list(thetaunit='radians', direction="clockwise", rotation=0)),
         title="All vowels produced by NZE speakers",
         legend=list(orientation="h", xanchor="center", x=0.5,y=0.008))
plot2

if(printPDF==TRUE)
{
  orca(plot2, "Figure7(a).pdf",format="pdf")
  orca(plot2, "Figure7(a).jpg",format="jpeg")
}
rm(p1,p2,p3,p4,p5,p6,p7,p8,p9,p10,p11,p12,p13)

3.4.2 All NZE notes

# correct order
colors = c(black, black, black, black, black)
p1=plot_smooth(x=NZE.gam.AR.Mod2, view="theta_uncut_z", cond=list(tokenPooled.ord="Bb2"), rm.ranef=TRUE)
Summary:
    * tokenPooled.ord : factor; set to the value(s): Bb2. 
    * theta_uncut_z : numeric predictor; with 30 values ranging from -2.627597 to -0.617214. 
    * subVowelInt : factor; set to the value(s): S3.ə. (Might be canceled as random effect, check below.) 
    * precSoundVowelInt : factor; set to the value(s): mezzoforte.F3. (Might be canceled as random effect, check below.) 
    * follSoundVowelInt : factor; set to the value(s): coronals.ə. (Might be canceled as random effect, check below.) 
    * NOTE : The following random effects columns are canceled: s(theta_uncut_z,subVowelInt),s(theta_uncut_z,precSoundVowelInt),s(theta_uncut_z,follSoundVowelInt)
 

p2=plot_smooth(x=NZE.gam.AR.Mod2, view="theta_uncut_z", cond=list(tokenPooled.ord="F3"), rm.ranef=TRUE)
Summary:
    * tokenPooled.ord : factor; set to the value(s): F3. 
    * theta_uncut_z : numeric predictor; with 30 values ranging from -2.627597 to -0.617214. 
    * subVowelInt : factor; set to the value(s): S3.ə. (Might be canceled as random effect, check below.) 
    * precSoundVowelInt : factor; set to the value(s): mezzoforte.F3. (Might be canceled as random effect, check below.) 
    * follSoundVowelInt : factor; set to the value(s): coronals.ə. (Might be canceled as random effect, check below.) 
    * NOTE : The following random effects columns are canceled: s(theta_uncut_z,subVowelInt),s(theta_uncut_z,precSoundVowelInt),s(theta_uncut_z,follSoundVowelInt)
 

p3=plot_smooth(x=NZE.gam.AR.Mod2, view="theta_uncut_z", cond=list(tokenPooled.ord="Bb3"), rm.ranef=TRUE)
Summary:
    * tokenPooled.ord : factor; set to the value(s): Bb3. 
    * theta_uncut_z : numeric predictor; with 30 values ranging from -2.627597 to -0.617214. 
    * subVowelInt : factor; set to the value(s): S3.ə. (Might be canceled as random effect, check below.) 
    * precSoundVowelInt : factor; set to the value(s): mezzoforte.F3. (Might be canceled as random effect, check below.) 
    * follSoundVowelInt : factor; set to the value(s): coronals.ə. (Might be canceled as random effect, check below.) 
    * NOTE : The following random effects columns are canceled: s(theta_uncut_z,subVowelInt),s(theta_uncut_z,precSoundVowelInt),s(theta_uncut_z,follSoundVowelInt)
 

p4=plot_smooth(x=NZE.gam.AR.Mod2, view="theta_uncut_z", cond=list(tokenPooled.ord="D4"), rm.ranef=TRUE)
Summary:
    * tokenPooled.ord : factor; set to the value(s): D4. 
    * theta_uncut_z : numeric predictor; with 30 values ranging from -2.627597 to -0.617214. 
    * subVowelInt : factor; set to the value(s): S3.ə. (Might be canceled as random effect, check below.) 
    * precSoundVowelInt : factor; set to the value(s): mezzoforte.F3. (Might be canceled as random effect, check below.) 
    * follSoundVowelInt : factor; set to the value(s): coronals.ə. (Might be canceled as random effect, check below.) 
    * NOTE : The following random effects columns are canceled: s(theta_uncut_z,subVowelInt),s(theta_uncut_z,precSoundVowelInt),s(theta_uncut_z,follSoundVowelInt)
 

p5=plot_smooth(x=NZE.gam.AR.Mod2, view="theta_uncut_z", cond=list(tokenPooled.ord="F4"), rm.ranef=TRUE)
Summary:
    * tokenPooled.ord : factor; set to the value(s): F4. 
    * theta_uncut_z : numeric predictor; with 30 values ranging from -2.627597 to -0.617214. 
    * subVowelInt : factor; set to the value(s): S3.ə. (Might be canceled as random effect, check below.) 
    * precSoundVowelInt : factor; set to the value(s): mezzoforte.F3. (Might be canceled as random effect, check below.) 
    * follSoundVowelInt : factor; set to the value(s): coronals.ə. (Might be canceled as random effect, check below.) 
    * NOTE : The following random effects columns are canceled: s(theta_uncut_z,subVowelInt),s(theta_uncut_z,precSoundVowelInt),s(theta_uncut_z,follSoundVowelInt)
 

smooth_names=c("Bb2","F3","Bb3","D4","F4")
# set Rho max to the max of the fit + 5
#max_fit = max(p1$fv$fit, p2$fv$fit, p3$fv$fit, p4$fv$fit, p5$fv$fit)
#maximum=max_fit+5
#rm(max_fit)
# plot in polar coordinates without confidence bounds
p=plot_ly(type='scatterpolar', mode='lines') %>%
  add_trace(theta=p1$fv$theta_uncut_z*180/pi, r=p1$fv$fit, line=list(color=colors[1], width=2.5), name=smooth_names[1]) %>%
  add_trace(theta=p2$fv$theta_uncut_z*180/pi, r=p2$fv$fit, line=list(color=colors[2], dash="dash", width=2.5), name=smooth_names[2]) %>%
  add_trace(theta=p3$fv$theta_uncut_z*180/pi, r=p3$fv$fit, line=list(color=colors[3], dash="dot", width=2.5), name=smooth_names[3]) %>%
  add_trace(theta=p4$fv$theta_uncut_z*180/pi, r=p4$fv$fit, line=list(color=colors[4], dash="dashdot", width=2.5), name=smooth_names[4]) %>%
  add_trace(theta=p5$fv$theta_uncut_z*180/pi, r=p5$fv$fit, line=list(color=colors[5], width=1),
            name=smooth_names[5]) %>%
  layout(polar=list(sector=c(20,160), radialaxis=list(angle=90, range=c(0,maximum)),
                    angularaxis=list(thetaunit='radians', direction="clockwise", rotation=0)),
         title="All notes produced by NZE speakers",
         legend=list(orientation="h", xanchor="center", x=0.5,y=0.012))
p

if(printPDF==TRUE)
{
  orca(p, "Figure7(b).pdf",format="pdf")
  orca(p, "Figure7(b).jpg",format="jpeg")
}
rm(p1,p2,p3,p4,p5)

3.5 Figure 8 -> H2 vowels and notes Tongan

3.5.1 All Tongan vowels

# use colors from PhD thesis (loaded above)
colors = c(ORANGE0, dark_blue, RED0, pink, GREEN0)
# run plot_smooth to grab values for fit, upper & lower bounds
p1=plot_smooth(x=Tongan.gam.AR.Mod2, view="theta_uncut_z", cond=list(tokenPooled.ord="i"), rm.ranef=TRUE)
Summary:
    * tokenPooled.ord : factor; set to the value(s): i. 
    * theta_uncut_z : numeric predictor; with 30 values ranging from -2.648777 to -0.708619. 
    * subVowelInt : factor; set to the value(s): S16.F3. (Might be canceled as random effect, check below.) 
    * precSoundVowelInt : factor; set to the value(s): mezzoforte.F3. (Might be canceled as random effect, check below.) 
    * follSoundVowelInt : factor; set to the value(s): mezzoforte.F3. (Might be canceled as random effect, check below.) 
    * NOTE : The following random effects columns are canceled: s(theta_uncut_z,subVowelInt),s(theta_uncut_z,precSoundVowelInt),s(theta_uncut_z,follSoundVowelInt)
 

p2=plot_smooth(x=Tongan.gam.AR.Mod2, view="theta_uncut_z", cond=list(tokenPooled.ord="e"), rm.ranef=TRUE)
Summary:
    * tokenPooled.ord : factor; set to the value(s): e. 
    * theta_uncut_z : numeric predictor; with 30 values ranging from -2.648777 to -0.708619. 
    * subVowelInt : factor; set to the value(s): S16.F3. (Might be canceled as random effect, check below.) 
    * precSoundVowelInt : factor; set to the value(s): mezzoforte.F3. (Might be canceled as random effect, check below.) 
    * follSoundVowelInt : factor; set to the value(s): mezzoforte.F3. (Might be canceled as random effect, check below.) 
    * NOTE : The following random effects columns are canceled: s(theta_uncut_z,subVowelInt),s(theta_uncut_z,precSoundVowelInt),s(theta_uncut_z,follSoundVowelInt)
 

p3=plot_smooth(x=Tongan.gam.AR.Mod2, view="theta_uncut_z", cond=list(tokenPooled.ord="a"), rm.ranef=TRUE)
Summary:
    * tokenPooled.ord : factor; set to the value(s): a. 
    * theta_uncut_z : numeric predictor; with 30 values ranging from -2.648777 to -0.708619. 
    * subVowelInt : factor; set to the value(s): S16.F3. (Might be canceled as random effect, check below.) 
    * precSoundVowelInt : factor; set to the value(s): mezzoforte.F3. (Might be canceled as random effect, check below.) 
    * follSoundVowelInt : factor; set to the value(s): mezzoforte.F3. (Might be canceled as random effect, check below.) 
    * NOTE : The following random effects columns are canceled: s(theta_uncut_z,subVowelInt),s(theta_uncut_z,precSoundVowelInt),s(theta_uncut_z,follSoundVowelInt)
 

p4=plot_smooth(x=Tongan.gam.AR.Mod2, view="theta_uncut_z", cond=list(tokenPooled.ord="o"), rm.ranef=TRUE)
Summary:
    * tokenPooled.ord : factor; set to the value(s): o. 
    * theta_uncut_z : numeric predictor; with 30 values ranging from -2.648777 to -0.708619. 
    * subVowelInt : factor; set to the value(s): S16.F3. (Might be canceled as random effect, check below.) 
    * precSoundVowelInt : factor; set to the value(s): mezzoforte.F3. (Might be canceled as random effect, check below.) 
    * follSoundVowelInt : factor; set to the value(s): mezzoforte.F3. (Might be canceled as random effect, check below.) 
    * NOTE : The following random effects columns are canceled: s(theta_uncut_z,subVowelInt),s(theta_uncut_z,precSoundVowelInt),s(theta_uncut_z,follSoundVowelInt)
 

p5=plot_smooth(x=Tongan.gam.AR.Mod2, view="theta_uncut_z", cond=list(tokenPooled.ord="u"), rm.ranef=TRUE)
Summary:
    * tokenPooled.ord : factor; set to the value(s): u. 
    * theta_uncut_z : numeric predictor; with 30 values ranging from -2.648777 to -0.708619. 
    * subVowelInt : factor; set to the value(s): S16.F3. (Might be canceled as random effect, check below.) 
    * precSoundVowelInt : factor; set to the value(s): mezzoforte.F3. (Might be canceled as random effect, check below.) 
    * follSoundVowelInt : factor; set to the value(s): mezzoforte.F3. (Might be canceled as random effect, check below.) 
    * NOTE : The following random effects columns are canceled: s(theta_uncut_z,subVowelInt),s(theta_uncut_z,precSoundVowelInt),s(theta_uncut_z,follSoundVowelInt)
 

smooth_names=c("/i/","/e/","/a/","/o/","/u/")
# set Rho max to the max of the fit + half the difference between max of the fit and the upper limit
# max_ul = max(p1$fv$ul, p2$fv$ul, p3$fv$ul, p4$fv$ul, p5$fv$ul)
# max_fit = max(p1$fv$fit, p2$fv$fit, p3$fv$fit, p4$fv$fit, p5$fv$fit)
# maximum = max_fit+((max_ul-max_fit)/2)
# rm(max_ul, max_fit)
maximum = max(p1$fv$ul, p2$fv$ul, p3$fv$ul, p4$fv$ul, p5$fv$ul)
# plot in polar coordinates with confidence bounds
plot1=plot_ly(type='scatterpolar', mode='lines') %>% 
  add_trace(theta=p1$fv$theta_uncut_z*180/pi, r=p1$fv$fit, line=list(color=colors[1], width=2.5),
            name=smooth_names[1]) %>% 
  add_trace(theta=p1$fv$theta_uncut_z*180/pi, r=p1$fv$ul, line=list(color=colors[1], dash="dot", width=0.5), showlegend=FALSE) %>% 
  add_trace(theta=p1$fv$theta_uncut_z*180/pi, r=p1$fv$ll, line=list(color=colors[1], dash="dot", width=0.5), showlegend=FALSE) %>% 
  add_trace(theta=p2$fv$theta_uncut_z*180/pi, r=p2$fv$fit, line=list(color=colors[2], width=2.5), 
            name=smooth_names[2]) %>% 
  add_trace(theta=p2$fv$theta_uncut_z*180/pi, r=p2$fv$ul, line=list(color=colors[2], dash="dot", width=0.5), showlegend=FALSE) %>% 
  add_trace(theta=p2$fv$theta_uncut_z*180/pi, r=p2$fv$ll, line=list(color=colors[2], dash="dot", width=0.5), showlegend=FALSE) %>%
  add_trace(theta=p3$fv$theta_uncut_z*180/pi, r=p3$fv$fit, line=list(color=colors[3], width=2.5), 
            name=smooth_names[3]) %>% 
  add_trace(theta=p3$fv$theta_uncut_z*180/pi, r=p3$fv$ul, line=list(color=colors[3], dash="dot", width=0.5), showlegend=FALSE) %>% 
  add_trace(theta=p3$fv$theta_uncut_z*180/pi, r=p3$fv$ll, line=list(color=colors[3], dash="dot", width=0.5), showlegend=FALSE) %>%
  add_trace(theta=p4$fv$theta_uncut_z*180/pi, r=p4$fv$fit, line=list(color=colors[4], width=2.5), 
            name=smooth_names[4]) %>% 
  add_trace(theta=p4$fv$theta_uncut_z*180/pi, r=p4$fv$ul, line=list(color=colors[4], dash="dot", width=0.5), showlegend=FALSE) %>% 
  add_trace(theta=p4$fv$theta_uncut_z*180/pi, r=p4$fv$ll, line=list(color=colors[4], dash="dot", width=0.5), showlegend=FALSE) %>%
  add_trace(theta=p5$fv$theta_uncut_z*180/pi, r=p5$fv$fit, line=list(color=colors[5], width=2.5), 
            name=smooth_names[5]) %>% 
  add_trace(theta=p5$fv$theta_uncut_z*180/pi, r=p5$fv$ul, line=list(color=colors[5], dash="dot", width=0.5), showlegend=FALSE) %>% 
  add_trace(theta=p5$fv$theta_uncut_z*180/pi, r=p5$fv$ll, line=list(color=colors[5], dash="dot", width=0.5), showlegend=FALSE) %>%
  layout(polar=list(sector=c(20,160), radialaxis=list(angle=90, range=c(0,maximum)),
                    angularaxis=list(thetaunit='radians', direction="clockwise", rotation=0)), 
         title="All vowels produced by Tongan speakers",
         legend=list(orientation="h", xanchor="center", x=0.5,y=0.012))
plot1

# # set Rho max to the max of the fit + 5
# max_fit = max(p1$fv$fit, p2$fv$fit, p3$fv$fit, p4$fv$fit, p5$fv$fit)
# maximum=max_fit+5
# rm(max_fit)
# 
# # plot in polar coordinates with confidence bounds
# plot2=plot_ly(type='scatterpolar', mode='lines') %>% 
#   add_trace(theta=p1$fv$theta_uncut_z*180/pi, r=p1$fv$fit, line=list(color=colors[1], width=2.5),
#             name=smooth_names[1]) %>% 
#   add_trace(theta=p2$fv$theta_uncut_z*180/pi, r=p2$fv$fit, line=list(color=colors[2], width=2.5), 
#             name=smooth_names[2]) %>% 
#   add_trace(theta=p3$fv$theta_uncut_z*180/pi, r=p3$fv$fit, line=list(color=colors[3], width=2.5), 
#             name=smooth_names[3]) %>% 
#   add_trace(theta=p4$fv$theta_uncut_z*180/pi, r=p4$fv$fit, line=list(color=colors[4], width=2.5), 
#             name=smooth_names[4]) %>% 
#   add_trace(theta=p5$fv$theta_uncut_z*180/pi, r=p5$fv$fit, line=list(color=colors[5], width=2.5), 
#             name=smooth_names[5]) %>% 
#   layout(polar=list(sector=c(20,160), radialaxis=list(angle=90, range=c(0,maximum)),
#                     angularaxis=list(thetaunit='radians', direction="clockwise", rotation=0)), 
#          title="All vowels produced by Tongan speakers",
#          legend=list(orientation="h", xanchor="center", x=0.5))
# plot2
if(printPDF==TRUE)
{
  orca(plot1, "Figure8(a).pdf",format="pdf")
  orca(plot1, "Figure8(a).jpg",format="jpeg")
}
  
rm(p1,p2,p3,p4,p5)

3.5.2 All Tongan notes

# use colors from PhD thesis (loaded above)
colors = c(black, black, black, black, black)
p1=plot_smooth(x=Tongan.gam.AR.Mod2, view="theta_uncut_z", cond=list(tokenPooled.ord="Bb2"), rm.ranef=TRUE)
Summary:
    * tokenPooled.ord : factor; set to the value(s): Bb2. 
    * theta_uncut_z : numeric predictor; with 30 values ranging from -2.648777 to -0.708619. 
    * subVowelInt : factor; set to the value(s): S16.F3. (Might be canceled as random effect, check below.) 
    * precSoundVowelInt : factor; set to the value(s): mezzoforte.F3. (Might be canceled as random effect, check below.) 
    * follSoundVowelInt : factor; set to the value(s): mezzoforte.F3. (Might be canceled as random effect, check below.) 
    * NOTE : The following random effects columns are canceled: s(theta_uncut_z,subVowelInt),s(theta_uncut_z,precSoundVowelInt),s(theta_uncut_z,follSoundVowelInt)
 

p2=plot_smooth(x=Tongan.gam.AR.Mod2, view="theta_uncut_z", cond=list(tokenPooled.ord="F3"), rm.ranef=TRUE)
Summary:
    * tokenPooled.ord : factor; set to the value(s): F3. 
    * theta_uncut_z : numeric predictor; with 30 values ranging from -2.648777 to -0.708619. 
    * subVowelInt : factor; set to the value(s): S16.F3. (Might be canceled as random effect, check below.) 
    * precSoundVowelInt : factor; set to the value(s): mezzoforte.F3. (Might be canceled as random effect, check below.) 
    * follSoundVowelInt : factor; set to the value(s): mezzoforte.F3. (Might be canceled as random effect, check below.) 
    * NOTE : The following random effects columns are canceled: s(theta_uncut_z,subVowelInt),s(theta_uncut_z,precSoundVowelInt),s(theta_uncut_z,follSoundVowelInt)
 

p3=plot_smooth(x=Tongan.gam.AR.Mod2, view="theta_uncut_z", cond=list(tokenPooled.ord="Bb3"), rm.ranef=TRUE)
Summary:
    * tokenPooled.ord : factor; set to the value(s): Bb3. 
    * theta_uncut_z : numeric predictor; with 30 values ranging from -2.648777 to -0.708619. 
    * subVowelInt : factor; set to the value(s): S16.F3. (Might be canceled as random effect, check below.) 
    * precSoundVowelInt : factor; set to the value(s): mezzoforte.F3. (Might be canceled as random effect, check below.) 
    * follSoundVowelInt : factor; set to the value(s): mezzoforte.F3. (Might be canceled as random effect, check below.) 
    * NOTE : The following random effects columns are canceled: s(theta_uncut_z,subVowelInt),s(theta_uncut_z,precSoundVowelInt),s(theta_uncut_z,follSoundVowelInt)
 

p4=plot_smooth(x=Tongan.gam.AR.Mod2, view="theta_uncut_z", cond=list(tokenPooled.ord="D4"), rm.ranef=TRUE)
Summary:
    * tokenPooled.ord : factor; set to the value(s): D4. 
    * theta_uncut_z : numeric predictor; with 30 values ranging from -2.648777 to -0.708619. 
    * subVowelInt : factor; set to the value(s): S16.F3. (Might be canceled as random effect, check below.) 
    * precSoundVowelInt : factor; set to the value(s): mezzoforte.F3. (Might be canceled as random effect, check below.) 
    * follSoundVowelInt : factor; set to the value(s): mezzoforte.F3. (Might be canceled as random effect, check below.) 
    * NOTE : The following random effects columns are canceled: s(theta_uncut_z,subVowelInt),s(theta_uncut_z,precSoundVowelInt),s(theta_uncut_z,follSoundVowelInt)
 

p5=plot_smooth(x=Tongan.gam.AR.Mod2, view="theta_uncut_z", cond=list(tokenPooled.ord="F4"), rm.ranef=TRUE)
Summary:
    * tokenPooled.ord : factor; set to the value(s): F4. 
    * theta_uncut_z : numeric predictor; with 30 values ranging from -2.648777 to -0.708619. 
    * subVowelInt : factor; set to the value(s): S16.F3. (Might be canceled as random effect, check below.) 
    * precSoundVowelInt : factor; set to the value(s): mezzoforte.F3. (Might be canceled as random effect, check below.) 
    * follSoundVowelInt : factor; set to the value(s): mezzoforte.F3. (Might be canceled as random effect, check below.) 
    * NOTE : The following random effects columns are canceled: s(theta_uncut_z,subVowelInt),s(theta_uncut_z,precSoundVowelInt),s(theta_uncut_z,follSoundVowelInt)
 

smooth_names=c("Bb2","F3","Bb3","D4","F4")
# plot in polar coordinates without confidence bounds
p=plot_ly(type='scatterpolar', mode='lines') %>% 
  add_trace(theta=p1$fv$theta_uncut_z*180/pi, r=p1$fv$fit, line=list(color=colors[1], width=2.5), name=smooth_names[1]) %>% 
  add_trace(theta=p2$fv$theta_uncut_z*180/pi, r=p2$fv$fit, line=list(color=colors[2], dash="dash", width=2.5), name=smooth_names[2]) %>% 
  add_trace(theta=p3$fv$theta_uncut_z*180/pi, r=p3$fv$fit, line=list(color=colors[3], dash="dot", width=2.5), name=smooth_names[3]) %>% 
  add_trace(theta=p4$fv$theta_uncut_z*180/pi, r=p4$fv$fit, line=list(color=colors[4], dash="dashdot", width=2.5), name=smooth_names[4]) %>% 
  add_trace(theta=p5$fv$theta_uncut_z*180/pi, r=p5$fv$fit, line=list(color=colors[5], width=1), 
            name=smooth_names[5]) %>% 
  layout(polar=list(sector=c(20,160), radialaxis=list(angle=90, range=c(0,maximum)),
                    angularaxis=list(thetaunit='radians', direction="clockwise", rotation=0)), 
         title="All notes produced by Tongan speakers",
         legend=list(orientation="h", xanchor="center", x=0.5,y=0.012))
p

if(printPDF==TRUE)
{
  orca(p, "Figure8(b).pdf",format="pdf")
  orca(p, "Figure8(b).jpg",format="jpeg")
}
  
rm(p1,p2,p3,p4,p5)

3.6 Figure 9 -> H2 selected vowels with notes

3.6.1 with NZE notes

colors = c(black, black, black, black, black,BROWN0, GRAY0, PURPLE0, pink, GREEN0)
# run plot_smooth to grab values for fit, upper & lower bounds
# NZE notes
p1=plot_smooth(x=NZE.gam.AR.Mod2, view="theta_uncut_z", cond=list(tokenPooled.ord="Bb2"), rm.ranef=TRUE)
Summary:
    * tokenPooled.ord : factor; set to the value(s): Bb2. 
    * theta_uncut_z : numeric predictor; with 30 values ranging from -2.627597 to -0.617214. 
    * subVowelInt : factor; set to the value(s): S3.ə. (Might be canceled as random effect, check below.) 
    * precSoundVowelInt : factor; set to the value(s): mezzoforte.F3. (Might be canceled as random effect, check below.) 
    * follSoundVowelInt : factor; set to the value(s): coronals.ə. (Might be canceled as random effect, check below.) 
    * NOTE : The following random effects columns are canceled: s(theta_uncut_z,subVowelInt),s(theta_uncut_z,precSoundVowelInt),s(theta_uncut_z,follSoundVowelInt)
 

p2=plot_smooth(x=NZE.gam.AR.Mod2, view="theta_uncut_z", cond=list(tokenPooled.ord="F3"), rm.ranef=TRUE)
Summary:
    * tokenPooled.ord : factor; set to the value(s): F3. 
    * theta_uncut_z : numeric predictor; with 30 values ranging from -2.627597 to -0.617214. 
    * subVowelInt : factor; set to the value(s): S3.ə. (Might be canceled as random effect, check below.) 
    * precSoundVowelInt : factor; set to the value(s): mezzoforte.F3. (Might be canceled as random effect, check below.) 
    * follSoundVowelInt : factor; set to the value(s): coronals.ə. (Might be canceled as random effect, check below.) 
    * NOTE : The following random effects columns are canceled: s(theta_uncut_z,subVowelInt),s(theta_uncut_z,precSoundVowelInt),s(theta_uncut_z,follSoundVowelInt)
 

p3=plot_smooth(x=NZE.gam.AR.Mod2, view="theta_uncut_z", cond=list(tokenPooled.ord="Bb3"), rm.ranef=TRUE)
Summary:
    * tokenPooled.ord : factor; set to the value(s): Bb3. 
    * theta_uncut_z : numeric predictor; with 30 values ranging from -2.627597 to -0.617214. 
    * subVowelInt : factor; set to the value(s): S3.ə. (Might be canceled as random effect, check below.) 
    * precSoundVowelInt : factor; set to the value(s): mezzoforte.F3. (Might be canceled as random effect, check below.) 
    * follSoundVowelInt : factor; set to the value(s): coronals.ə. (Might be canceled as random effect, check below.) 
    * NOTE : The following random effects columns are canceled: s(theta_uncut_z,subVowelInt),s(theta_uncut_z,precSoundVowelInt),s(theta_uncut_z,follSoundVowelInt)
 

p4=plot_smooth(x=NZE.gam.AR.Mod2, view="theta_uncut_z", cond=list(tokenPooled.ord="D4"), rm.ranef=TRUE)
Summary:
    * tokenPooled.ord : factor; set to the value(s): D4. 
    * theta_uncut_z : numeric predictor; with 30 values ranging from -2.627597 to -0.617214. 
    * subVowelInt : factor; set to the value(s): S3.ə. (Might be canceled as random effect, check below.) 
    * precSoundVowelInt : factor; set to the value(s): mezzoforte.F3. (Might be canceled as random effect, check below.) 
    * follSoundVowelInt : factor; set to the value(s): coronals.ə. (Might be canceled as random effect, check below.) 
    * NOTE : The following random effects columns are canceled: s(theta_uncut_z,subVowelInt),s(theta_uncut_z,precSoundVowelInt),s(theta_uncut_z,follSoundVowelInt)
 

p5=plot_smooth(x=NZE.gam.AR.Mod2, view="theta_uncut_z", cond=list(tokenPooled.ord="F4"), rm.ranef=TRUE)
Summary:
    * tokenPooled.ord : factor; set to the value(s): F4. 
    * theta_uncut_z : numeric predictor; with 30 values ranging from -2.627597 to -0.617214. 
    * subVowelInt : factor; set to the value(s): S3.ə. (Might be canceled as random effect, check below.) 
    * precSoundVowelInt : factor; set to the value(s): mezzoforte.F3. (Might be canceled as random effect, check below.) 
    * follSoundVowelInt : factor; set to the value(s): coronals.ə. (Might be canceled as random effect, check below.) 
    * NOTE : The following random effects columns are canceled: s(theta_uncut_z,subVowelInt),s(theta_uncut_z,precSoundVowelInt),s(theta_uncut_z,follSoundVowelInt)
 

# vowels
p6=plot_smooth(x=NZE.gam.AR.Mod2, view="theta_uncut_z", cond=list(tokenPooled.ord="ə"), rm.ranef=TRUE)
Summary:
    * tokenPooled.ord : factor; set to the value(s): ə. 
    * theta_uncut_z : numeric predictor; with 30 values ranging from -2.627597 to -0.617214. 
    * subVowelInt : factor; set to the value(s): S3.ə. (Might be canceled as random effect, check below.) 
    * precSoundVowelInt : factor; set to the value(s): mezzoforte.F3. (Might be canceled as random effect, check below.) 
    * follSoundVowelInt : factor; set to the value(s): coronals.ə. (Might be canceled as random effect, check below.) 
    * NOTE : The following random effects columns are canceled: s(theta_uncut_z,subVowelInt),s(theta_uncut_z,precSoundVowelInt),s(theta_uncut_z,follSoundVowelInt)
 

p7=plot_smooth(x=NZE.gam.AR.Mod2, view="theta_uncut_z", cond=list(tokenPooled.ord="ə#"), rm.ranef=TRUE)
Summary:
    * tokenPooled.ord : factor; set to the value(s): ə#. 
    * theta_uncut_z : numeric predictor; with 30 values ranging from -2.627597 to -0.617214. 
    * subVowelInt : factor; set to the value(s): S3.ə. (Might be canceled as random effect, check below.) 
    * precSoundVowelInt : factor; set to the value(s): mezzoforte.F3. (Might be canceled as random effect, check below.) 
    * follSoundVowelInt : factor; set to the value(s): coronals.ə. (Might be canceled as random effect, check below.) 
    * NOTE : The following random effects columns are canceled: s(theta_uncut_z,subVowelInt),s(theta_uncut_z,precSoundVowelInt),s(theta_uncut_z,follSoundVowelInt)
 

p8=plot_smooth(x=NZE.gam.AR.Mod2, view="theta_uncut_z", cond=list(tokenPooled.ord="ɒ"), rm.ranef=TRUE)
Summary:
    * tokenPooled.ord : factor; set to the value(s): ɒ. 
    * theta_uncut_z : numeric predictor; with 30 values ranging from -2.627597 to -0.617214. 
    * subVowelInt : factor; set to the value(s): S3.ə. (Might be canceled as random effect, check below.) 
    * precSoundVowelInt : factor; set to the value(s): mezzoforte.F3. (Might be canceled as random effect, check below.) 
    * follSoundVowelInt : factor; set to the value(s): coronals.ə. (Might be canceled as random effect, check below.) 
    * NOTE : The following random effects columns are canceled: s(theta_uncut_z,subVowelInt),s(theta_uncut_z,precSoundVowelInt),s(theta_uncut_z,follSoundVowelInt)
 

p9=plot_smooth(x=Tongan.gam.AR.Mod2, view="theta_uncut_z", cond=list(tokenPooled.ord="o"), rm.ranef=TRUE)
Summary:
    * tokenPooled.ord : factor; set to the value(s): o. 
    * theta_uncut_z : numeric predictor; with 30 values ranging from -2.648777 to -0.708619. 
    * subVowelInt : factor; set to the value(s): S16.F3. (Might be canceled as random effect, check below.) 
    * precSoundVowelInt : factor; set to the value(s): mezzoforte.F3. (Might be canceled as random effect, check below.) 
    * follSoundVowelInt : factor; set to the value(s): mezzoforte.F3. (Might be canceled as random effect, check below.) 
    * NOTE : The following random effects columns are canceled: s(theta_uncut_z,subVowelInt),s(theta_uncut_z,precSoundVowelInt),s(theta_uncut_z,follSoundVowelInt)
 

p10=plot_smooth(x=Tongan.gam.AR.Mod2, view="theta_uncut_z", cond=list(tokenPooled.ord="u"), rm.ranef=TRUE)
Summary:
    * tokenPooled.ord : factor; set to the value(s): u. 
    * theta_uncut_z : numeric predictor; with 30 values ranging from -2.648777 to -0.708619. 
    * subVowelInt : factor; set to the value(s): S16.F3. (Might be canceled as random effect, check below.) 
    * precSoundVowelInt : factor; set to the value(s): mezzoforte.F3. (Might be canceled as random effect, check below.) 
    * follSoundVowelInt : factor; set to the value(s): mezzoforte.F3. (Might be canceled as random effect, check below.) 
    * NOTE : The following random effects columns are canceled: s(theta_uncut_z,subVowelInt),s(theta_uncut_z,precSoundVowelInt),s(theta_uncut_z,follSoundVowelInt)
 

smooth_names=c("Bb2 NZE","F3 NZE","Bb3 NZE","D4 NZE","F4 NZE","non-final schwa /ə/ NZE","final schwa /ə#/ NZE","LOT /ɒ/ NZE","/o/ Tongan","/u/ Tongan")
# set Rho max to the max of the fit + 5
max_fit = max(p1$fv$fit, p2$fv$fit, p3$fv$fit, p4$fv$fit, p5$fv$fit, p6$fv$fit, p7$fv$fit, p8$fv$fit, p9$fv$fit, p10$fv$fit)
maximum=max_fit+5
rm(max_fit)
# plot in polar coordinates without confidence bounds
plot2=plot_ly(type='scatterpolar', mode='lines') %>%
  add_trace(theta=p1$fv$theta_uncut_z*180/pi, r=p1$fv$fit, line=list(color=colors[1], width=2.5), name=smooth_names[1]) %>%
  add_trace(theta=p2$fv$theta_uncut_z*180/pi, r=p2$fv$fit, line=list(color=colors[2], dash="dash", width=2.5), name=smooth_names[2]) %>%
  add_trace(theta=p3$fv$theta_uncut_z*180/pi, r=p3$fv$fit, line=list(color=colors[3], dash="dot", width=2.5), name=smooth_names[3]) %>%
  add_trace(theta=p4$fv$theta_uncut_z*180/pi, r=p4$fv$fit, line=list(color=colors[4], dash="dashdot", width=2.5), name=smooth_names[4]) %>%
  add_trace(theta=p5$fv$theta_uncut_z*180/pi, r=p5$fv$fit, line=list(color=colors[5], width=1), name=smooth_names[5]) %>%
  add_trace(theta=p6$fv$theta_uncut_z*180/pi, r=p6$fv$fit, line=list(color=colors[6], width=2.5), name=smooth_names[6]) %>%
  add_trace(theta=p7$fv$theta_uncut_z*180/pi, r=p7$fv$fit, line=list(color=colors[7], width=2.5), name=smooth_names[7]) %>%
  add_trace(theta=p8$fv$theta_uncut_z*180/pi, r=p8$fv$fit, line=list(color=colors[8], dash="dash", width=2.5), name=smooth_names[8]) %>%
  add_trace(theta=p9$fv$theta_uncut_z*180/pi, r=p9$fv$fit, line=list(color=colors[9], width=2.5), name=smooth_names[9]) %>%
  add_trace(theta=p10$fv$theta_uncut_z*180/pi, r=p10$fv$fit, line=list(color=colors[10], width=2.5),
name=smooth_names[10]) %>%
  layout(polar=list(sector=c(20,160), radialaxis=list(angle=90, range=c(0,maximum)),
                    angularaxis=list(thetaunit='radians', direction="clockwise", rotation=0)),
         title="Tongan & NZE vowels closest to playing position with NZE notes",legend=list(orientation="h", xanchor="center", x=0.5,y=0.008))
plot2

if(printPDF==TRUE)
{
  orca(plot2, "Figure9(a).pdf",format="pdf")
  orca(plot2, "Figure9(a).jpeg",format="jpeg")
}
rm(p1,p2,p3,p4,p5,p6,p7,p8,p9,p10)

3.6.2 with Tongan notes

colors = c(black, black, black, black, black,BROWN0, GRAY0, PURPLE0, pink, GREEN0)
# run plot_smooth to grab values for fit, upper & lower bounds
# Tongan notes
p1=plot_smooth(x=Tongan.gam.AR.Mod2, view="theta_uncut_z", cond=list(tokenPooled.ord="Bb2"), rm.ranef=TRUE)
Summary:
    * tokenPooled.ord : factor; set to the value(s): Bb2. 
    * theta_uncut_z : numeric predictor; with 30 values ranging from -2.648777 to -0.708619. 
    * subVowelInt : factor; set to the value(s): S16.F3. (Might be canceled as random effect, check below.) 
    * precSoundVowelInt : factor; set to the value(s): mezzoforte.F3. (Might be canceled as random effect, check below.) 
    * follSoundVowelInt : factor; set to the value(s): mezzoforte.F3. (Might be canceled as random effect, check below.) 
    * NOTE : The following random effects columns are canceled: s(theta_uncut_z,subVowelInt),s(theta_uncut_z,precSoundVowelInt),s(theta_uncut_z,follSoundVowelInt)
 

p2=plot_smooth(x=Tongan.gam.AR.Mod2, view="theta_uncut_z", cond=list(tokenPooled.ord="F3"), rm.ranef=TRUE)
Summary:
    * tokenPooled.ord : factor; set to the value(s): F3. 
    * theta_uncut_z : numeric predictor; with 30 values ranging from -2.648777 to -0.708619. 
    * subVowelInt : factor; set to the value(s): S16.F3. (Might be canceled as random effect, check below.) 
    * precSoundVowelInt : factor; set to the value(s): mezzoforte.F3. (Might be canceled as random effect, check below.) 
    * follSoundVowelInt : factor; set to the value(s): mezzoforte.F3. (Might be canceled as random effect, check below.) 
    * NOTE : The following random effects columns are canceled: s(theta_uncut_z,subVowelInt),s(theta_uncut_z,precSoundVowelInt),s(theta_uncut_z,follSoundVowelInt)
 

p3=plot_smooth(x=Tongan.gam.AR.Mod2, view="theta_uncut_z", cond=list(tokenPooled.ord="Bb3"), rm.ranef=TRUE)
Summary:
    * tokenPooled.ord : factor; set to the value(s): Bb3. 
    * theta_uncut_z : numeric predictor; with 30 values ranging from -2.648777 to -0.708619. 
    * subVowelInt : factor; set to the value(s): S16.F3. (Might be canceled as random effect, check below.) 
    * precSoundVowelInt : factor; set to the value(s): mezzoforte.F3. (Might be canceled as random effect, check below.) 
    * follSoundVowelInt : factor; set to the value(s): mezzoforte.F3. (Might be canceled as random effect, check below.) 
    * NOTE : The following random effects columns are canceled: s(theta_uncut_z,subVowelInt),s(theta_uncut_z,precSoundVowelInt),s(theta_uncut_z,follSoundVowelInt)
 

p4=plot_smooth(x=Tongan.gam.AR.Mod2, view="theta_uncut_z", cond=list(tokenPooled.ord="D4"), rm.ranef=TRUE)
Summary:
    * tokenPooled.ord : factor; set to the value(s): D4. 
    * theta_uncut_z : numeric predictor; with 30 values ranging from -2.648777 to -0.708619. 
    * subVowelInt : factor; set to the value(s): S16.F3. (Might be canceled as random effect, check below.) 
    * precSoundVowelInt : factor; set to the value(s): mezzoforte.F3. (Might be canceled as random effect, check below.) 
    * follSoundVowelInt : factor; set to the value(s): mezzoforte.F3. (Might be canceled as random effect, check below.) 
    * NOTE : The following random effects columns are canceled: s(theta_uncut_z,subVowelInt),s(theta_uncut_z,precSoundVowelInt),s(theta_uncut_z,follSoundVowelInt)
 

p5=plot_smooth(x=Tongan.gam.AR.Mod2, view="theta_uncut_z", cond=list(tokenPooled.ord="F4"), rm.ranef=TRUE)
Summary:
    * tokenPooled.ord : factor; set to the value(s): F4. 
    * theta_uncut_z : numeric predictor; with 30 values ranging from -2.648777 to -0.708619. 
    * subVowelInt : factor; set to the value(s): S16.F3. (Might be canceled as random effect, check below.) 
    * precSoundVowelInt : factor; set to the value(s): mezzoforte.F3. (Might be canceled as random effect, check below.) 
    * follSoundVowelInt : factor; set to the value(s): mezzoforte.F3. (Might be canceled as random effect, check below.) 
    * NOTE : The following random effects columns are canceled: s(theta_uncut_z,subVowelInt),s(theta_uncut_z,precSoundVowelInt),s(theta_uncut_z,follSoundVowelInt)
 

# vowels
p6=plot_smooth(x=NZE.gam.AR.Mod2, view="theta_uncut_z", cond=list(tokenPooled.ord="ə"), rm.ranef=TRUE)
Summary:
    * tokenPooled.ord : factor; set to the value(s): ə. 
    * theta_uncut_z : numeric predictor; with 30 values ranging from -2.627597 to -0.617214. 
    * subVowelInt : factor; set to the value(s): S3.ə. (Might be canceled as random effect, check below.) 
    * precSoundVowelInt : factor; set to the value(s): mezzoforte.F3. (Might be canceled as random effect, check below.) 
    * follSoundVowelInt : factor; set to the value(s): coronals.ə. (Might be canceled as random effect, check below.) 
    * NOTE : The following random effects columns are canceled: s(theta_uncut_z,subVowelInt),s(theta_uncut_z,precSoundVowelInt),s(theta_uncut_z,follSoundVowelInt)
 

p7=plot_smooth(x=NZE.gam.AR.Mod2, view="theta_uncut_z", cond=list(tokenPooled.ord="ə#"), rm.ranef=TRUE)
Summary:
    * tokenPooled.ord : factor; set to the value(s): ə#. 
    * theta_uncut_z : numeric predictor; with 30 values ranging from -2.627597 to -0.617214. 
    * subVowelInt : factor; set to the value(s): S3.ə. (Might be canceled as random effect, check below.) 
    * precSoundVowelInt : factor; set to the value(s): mezzoforte.F3. (Might be canceled as random effect, check below.) 
    * follSoundVowelInt : factor; set to the value(s): coronals.ə. (Might be canceled as random effect, check below.) 
    * NOTE : The following random effects columns are canceled: s(theta_uncut_z,subVowelInt),s(theta_uncut_z,precSoundVowelInt),s(theta_uncut_z,follSoundVowelInt)
 

p8=plot_smooth(x=NZE.gam.AR.Mod2, view="theta_uncut_z", cond=list(tokenPooled.ord="ɒ"), rm.ranef=TRUE)
Summary:
    * tokenPooled.ord : factor; set to the value(s): ɒ. 
    * theta_uncut_z : numeric predictor; with 30 values ranging from -2.627597 to -0.617214. 
    * subVowelInt : factor; set to the value(s): S3.ə. (Might be canceled as random effect, check below.) 
    * precSoundVowelInt : factor; set to the value(s): mezzoforte.F3. (Might be canceled as random effect, check below.) 
    * follSoundVowelInt : factor; set to the value(s): coronals.ə. (Might be canceled as random effect, check below.) 
    * NOTE : The following random effects columns are canceled: s(theta_uncut_z,subVowelInt),s(theta_uncut_z,precSoundVowelInt),s(theta_uncut_z,follSoundVowelInt)
 

p9=plot_smooth(x=Tongan.gam.AR.Mod2, view="theta_uncut_z", cond=list(tokenPooled.ord="o"), rm.ranef=TRUE)
Summary:
    * tokenPooled.ord : factor; set to the value(s): o. 
    * theta_uncut_z : numeric predictor; with 30 values ranging from -2.648777 to -0.708619. 
    * subVowelInt : factor; set to the value(s): S16.F3. (Might be canceled as random effect, check below.) 
    * precSoundVowelInt : factor; set to the value(s): mezzoforte.F3. (Might be canceled as random effect, check below.) 
    * follSoundVowelInt : factor; set to the value(s): mezzoforte.F3. (Might be canceled as random effect, check below.) 
    * NOTE : The following random effects columns are canceled: s(theta_uncut_z,subVowelInt),s(theta_uncut_z,precSoundVowelInt),s(theta_uncut_z,follSoundVowelInt)
 

p10=plot_smooth(x=Tongan.gam.AR.Mod2, view="theta_uncut_z", cond=list(tokenPooled.ord="u"), rm.ranef=TRUE)
Summary:
    * tokenPooled.ord : factor; set to the value(s): u. 
    * theta_uncut_z : numeric predictor; with 30 values ranging from -2.648777 to -0.708619. 
    * subVowelInt : factor; set to the value(s): S16.F3. (Might be canceled as random effect, check below.) 
    * precSoundVowelInt : factor; set to the value(s): mezzoforte.F3. (Might be canceled as random effect, check below.) 
    * follSoundVowelInt : factor; set to the value(s): mezzoforte.F3. (Might be canceled as random effect, check below.) 
    * NOTE : The following random effects columns are canceled: s(theta_uncut_z,subVowelInt),s(theta_uncut_z,precSoundVowelInt),s(theta_uncut_z,follSoundVowelInt)
 

smooth_names=c("Bb2 Tongan","F3 Tongan","Bb3 Tongan","D4 Tongan","F4 Tongan","non-final schwa /ə/ NZE","final schwa /ə#/ NZE","LOT /ɒ/ NZE","/o/ Tongan","/u/ Tongan")
# # set Rho max to the max of the fit + 5
# max_fit = max(p1$fv$fit, p2$fv$fit, p3$fv$fit, p4$fv$fit, p5$fv$fit, p6$fv$fit, p7$fv$fit, p8$fv$fit, p9$fv$fit, p10$fv$fit)
# maximum=max_fit+5
# rm(max_fit)
# 
# # plot in polar coordinates with confidence bounds
# plot1=plot_ly(type='scatterpolar', mode='lines') %>%
#   add_trace(theta=p1$fv$theta_uncut_z*180/pi, r=p1$fv$fit, line=list(color=colors[1], width=2.5), name=smooth_names[1]) %>%
#   add_trace(theta=p1$fv$theta_uncut_z*180/pi, r=p1$fv$ul, line=list(color=colors[1], dash="dot", width=0.5), showlegend=FALSE) %>%
#   add_trace(theta=p1$fv$theta_uncut_z*180/pi, r=p1$fv$ll, line=list(color=colors[1], dash="dot", width=0.5), showlegend=FALSE) %>%
#   add_trace(theta=p2$fv$theta_uncut_z*180/pi, r=p2$fv$fit, line=list(color=colors[2], width=2.5), name=smooth_names[2]) %>%
#   add_trace(theta=p2$fv$theta_uncut_z*180/pi, r=p2$fv$ul, line=list(color=colors[2], dash="dot", width=0.5), showlegend=FALSE) %>%
#   add_trace(theta=p2$fv$theta_uncut_z*180/pi, r=p2$fv$ll, line=list(color=colors[2], dash="dot", width=0.5), showlegend=FALSE) %>%
#   add_trace(theta=p3$fv$theta_uncut_z*180/pi, r=p3$fv$fit, line=list(color=colors[3], dash="dash", width=2.5), name=smooth_names[3]) %>%
#   add_trace(theta=p3$fv$theta_uncut_z*180/pi, r=p3$fv$ul, line=list(color=colors[3], dash="dash", width=0.5), showlegend=FALSE) %>%
#   add_trace(theta=p3$fv$theta_uncut_z*180/pi, r=p3$fv$ll, line=list(color=colors[3], dash="dash", width=0.5), showlegend=FALSE) %>%
#   add_trace(theta=p4$fv$theta_uncut_z*180/pi, r=p4$fv$fit, line=list(color=colors[4], width=2.5),
#             name=smooth_names[4]) %>%
#   add_trace(theta=p4$fv$theta_uncut_z*180/pi, r=p4$fv$ul, line=list(color=colors[4], dash="dot", width=0.5), showlegend=FALSE) %>%
#   add_trace(theta=p4$fv$theta_uncut_z*180/pi, r=p4$fv$ll, line=list(color=colors[4], dash="dot", width=0.5), showlegend=FALSE) %>%
#   add_trace(theta=p5$fv$theta_uncut_z*180/pi, r=p5$fv$fit, line=list(color=colors[5], width=2.5),
#             name=smooth_names[5]) %>%
#   add_trace(theta=p5$fv$theta_uncut_z*180/pi, r=p5$fv$ul, line=list(color=colors[5], dash="dot", width=0.5), showlegend=FALSE) %>%
#   add_trace(theta=p5$fv$theta_uncut_z*180/pi, r=p5$fv$ll, line=list(color=colors[5], dash="dot", width=0.5), showlegend=FALSE) %>%
#   add_trace(theta=p6$fv$theta_uncut_z*180/pi, r=p6$fv$fit, line=list(color=colors[6], width=1),
#             name=smooth_names[6]) %>%
#   add_trace(theta=p6$fv$theta_uncut_z*180/pi, r=p6$fv$ul, line=list(color=colors[6], dash="dot", width=0.5), showlegend=FALSE) %>%
#   add_trace(theta=p6$fv$theta_uncut_z*180/pi, r=p6$fv$ll, line=list(color=colors[6], dash="dot", width=0.5), showlegend=FALSE) %>%
#   add_trace(theta=p7$fv$theta_uncut_z*180/pi, r=p7$fv$fit, line=list(color=colors[7], dash="dashdot", width=2.5), name=smooth_names[7]) %>%
#   add_trace(theta=p7$fv$theta_uncut_z*180/pi, r=p7$fv$ul, line=list(color=colors[7], dash="dashdot", width=0.5), showlegend=FALSE) %>%
#   add_trace(theta=p7$fv$theta_uncut_z*180/pi, r=p7$fv$ll, line=list(color=colors[7], dash="dashdot", width=0.5), showlegend=FALSE) %>%
#   add_trace(theta=p8$fv$theta_uncut_z*180/pi, r=p8$fv$fit, line=list(color=colors[8], dash="dot", width=2.5), name=smooth_names[8]) %>%
#   add_trace(theta=p8$fv$theta_uncut_z*180/pi, r=p8$fv$ul, line=list(color=colors[8], dash="dot", width=0.5), showlegend=FALSE) %>%
#   add_trace(theta=p8$fv$theta_uncut_z*180/pi, r=p8$fv$ll, line=list(color=colors[8], dash="dot", width=0.5), showlegend=FALSE) %>%
#   add_trace(theta=p9$fv$theta_uncut_z*180/pi, r=p9$fv$fit, line=list(color=colors[9], dash="dash", width=2.5), name=smooth_names[9]) %>%
#   add_trace(theta=p9$fv$theta_uncut_z*180/pi, r=p9$fv$ul, line=list(color=colors[9], dash="dot", width=0.5), showlegend=FALSE) %>%
#   add_trace(theta=p9$fv$theta_uncut_z*180/pi, r=p9$fv$ll, line=list(color=colors[9], dash="dot", width=0.5), showlegend=FALSE) %>%
#   add_trace(theta=p10$fv$theta_uncut_z*180/pi, r=p10$fv$fit, line=list(color=colors[10], width=2.5),
#             name=smooth_names[10]) %>%
#   add_trace(theta=p10$fv$theta_uncut_z*180/pi, r=p10$fv$ul, line=list(color=colors[10], dash="dot", width=0.5), showlegend=FALSE) %>%
#   add_trace(theta=p10$fv$theta_uncut_z*180/pi, r=p10$fv$ll, line=list(color=colors[10], dash="dot", width=0.5), showlegend=FALSE) %>%
#   layout(polar=list(sector=c(20,160), radialaxis=list(angle=90, range=c(0,maximum)),
#                     angularaxis=list(thetaunit='radians', direction="clockwise", rotation=0)),
#          title="Tongan & NZE vowels closest to playing position with Tongan notes")
# plot1
# set Rho max to the max of the fit + 5
max_fit = max(p1$fv$fit, p2$fv$fit, p3$fv$fit, p4$fv$fit, p5$fv$fit, p6$fv$fit, p7$fv$fit, p8$fv$fit, p9$fv$fit, p10$fv$fit)
maximum=max_fit+5
rm(max_fit)
# plot in polar coordinates without confidence bounds
plot2=plot_ly(type='scatterpolar', mode='lines') %>%
  add_trace(theta=p1$fv$theta_uncut_z*180/pi, r=p1$fv$fit, line=list(color=colors[1], width=2.5), name=smooth_names[1]) %>%
  add_trace(theta=p2$fv$theta_uncut_z*180/pi, r=p2$fv$fit, line=list(color=colors[2], dash="dash", width=2.5), name=smooth_names[2]) %>%
  add_trace(theta=p3$fv$theta_uncut_z*180/pi, r=p3$fv$fit, line=list(color=colors[3], dash="dot", width=2.5), name=smooth_names[3]) %>%
  add_trace(theta=p4$fv$theta_uncut_z*180/pi, r=p4$fv$fit, line=list(color=colors[4], dash="dashdot", width=2.5), name=smooth_names[4]) %>%
  add_trace(theta=p5$fv$theta_uncut_z*180/pi, r=p5$fv$fit, line=list(color=colors[5], width=1), name=smooth_names[5]) %>%
  add_trace(theta=p6$fv$theta_uncut_z*180/pi, r=p6$fv$fit, line=list(color=colors[6], width=2.5), name=smooth_names[6]) %>%
  add_trace(theta=p7$fv$theta_uncut_z*180/pi, r=p7$fv$fit, line=list(color=colors[7], width=2.5), name=smooth_names[7]) %>%
  add_trace(theta=p8$fv$theta_uncut_z*180/pi, r=p8$fv$fit, line=list(color=colors[8], dash="dash", width=2.5), name=smooth_names[8]) %>%
  add_trace(theta=p9$fv$theta_uncut_z*180/pi, r=p9$fv$fit, line=list(color=colors[9], width=2.5), name=smooth_names[9]) %>%
  add_trace(theta=p10$fv$theta_uncut_z*180/pi, r=p10$fv$fit, line=list(color=colors[10], width=2.5),
name=smooth_names[10]) %>%
  layout(polar=list(sector=c(20,160), radialaxis=list(angle=90, range=c(0,maximum)),
                    angularaxis=list(thetaunit='radians', direction="clockwise", rotation=0)),
         title="Tongan & NZE vowels closest to playing position with Tongan notes",legend=list(orientation="h", xanchor="center", x=0.5,y=0.012))
plot2

if(printPDF==TRUE)
{
  orca(plot2, "Figure9(b).pdf",format="pdf")
  orca(plot2, "Figure9(b).jpeg",format="jpeg")
}
  
rm(p1,p2,p3,p4,p5,p6,p7,p8,p9,p10)

3.7 Figure 10 ‘cardinal vowels’ -> updated version using only vowels surrounded by coronals

# create dfNZE & dfTongan -> df already loaded and manipulated above
dfNZE <- subset(df,df$native_lg=="NZE")
dfNZE$tokenPooled <- factor(dfNZE$tokenPooled, levels = c("ɐː","ɐ","ɛ","ɵː","e","iː","ʉː","ʊ","oː","ɒ","ɘ","ə","ə#","Bb2","F3","Bb3","D4","F4"))
dfNZE$playing_proficiency <- as.factor(dfNZE$playing_proficiency)
dfNZE$note_intensity[is.na(dfNZE$note_intensity)] = "NULL"
dfNZE$subVowelInt <- interaction(dfNZE$subject, dfNZE$tokenPooled)
dfNZE$precSoundVowelInt <- interaction(dfNZE$speech_prec_pooled, dfNZE$tokenPooled)
dfNZE$follSoundVowelInt <- interaction(dfNZE$speech_fol_pooled, dfNZE$tokenPooled)
dfNZE$tokenPooled.ord <- as.ordered(dfNZE$tokenPooled)
contrasts(dfNZE$tokenPooled.ord) <- "contr.treatment"
dfNZE$vowels_pooled.ord <- as.ordered(dfNZE$vowels_pooled)
contrasts(dfNZE$vowels_pooled.ord) <- "contr.treatment"
dfNZE$sex.ord <- as.ordered(dfNZE$sex)
contrasts(dfNZE$sex.ord) <- "contr.treatment"
dfNZE$playing_proficiency.ord <- as.ordered(dfNZE$playing_proficiency)
contrasts(dfNZE$playing_proficiency.ord) <- "contr.treatment"
dfNZE$start <- dfNZE$points==1
dfTongan <- subset(df,df$native_lg=="Tongan")
dfTongan$tokenPooled <- factor(dfTongan$tokenPooled, levels = c("aː","a","eː","e","iː","i","uː","u","oː","o","Bb2","F3","Bb3","D4","F4"))
dfTongan$tokenPooled[dfTongan$tokenPooled == "aː"] = "a"
dfTongan$tokenPooled[dfTongan$tokenPooled == "eː"] = "e"
dfTongan$tokenPooled[dfTongan$tokenPooled == "iː"] = "i"
dfTongan$tokenPooled[dfTongan$tokenPooled == "uː"] = "u"
dfTongan$tokenPooled[dfTongan$tokenPooled == "oː"] = "o"
dfTongan$tokenPooled <- factor(dfTongan$tokenPooled)
dfTongan$playing_proficiency <- as.factor(dfTongan$playing_proficiency)
dfTongan$speech_prec_pooled[is.na(dfTongan$speech_prec_pooled)] = "NULL"
dfTongan$speech_fol_pooled[is.na(dfTongan$speech_fol_pooled)] = "NULL"
dfTongan$subVowelInt <- interaction(dfTongan$subject, dfTongan$tokenPooled)
dfTongan$precSoundVowelInt <- interaction(dfTongan$speech_prec_pooled, dfTongan$tokenPooled)
dfTongan$follSoundVowelInt <- interaction(dfTongan$speech_fol_pooled, dfTongan$tokenPooled)
dfTongan$tokenPooled.ord <- as.ordered(dfTongan$tokenPooled)
contrasts(dfTongan$tokenPooled.ord) <- "contr.treatment"
dfTongan$vowels_pooled.ord <- as.ordered(dfTongan$vowels_pooled)
contrasts(dfTongan$vowels_pooled.ord) <- "contr.treatment"
dfTongan$sex.ord <- as.ordered(dfTongan$sex)
contrasts(dfTongan$sex.ord) <- "contr.treatment"
dfTongan$playing_proficiency.ord <- as.ordered(dfTongan$playing_proficiency)
contrasts(dfTongan$playing_proficiency.ord) <- "contr.treatment"
dfTongan$start <- dfTongan$points==1
# # inspect vowel token numbers in different preceding and following contexts
# cat("\ndfNZE$speech_prec_pooled\n")
# table(dfNZE$speech_prec_pooled)
# cat("\ndfNZE$speech_fol_pooled\n")
# table(dfNZE$speech_fol_pooled)
# cat("\ndfTongan$speech_prec_pooled\n")
# table(dfTongan$speech_prec_pooled)
# cat("\ndfNZE$speech_fol_pooled\n")
# table(dfTongan$speech_fol_pooled)
# make copies of dfNZE and dfTongan
dat_NZE = dfNZE
dat_Tongan = dfTongan
# predict values from models
dat_NZE$predicted_values = predict(NZE.gam.AR.Mod2)
dat_Tongan$predicted_values = predict(Tongan.gam.AR.Mod2)
# create new data.frames
NZE_FLEECE = dat_NZE[dat_NZE$tokenPooled == "iː" & dat_NZE$speech_prec_pooled == "coronals" & dat_NZE$speech_fol_pooled == "coronals",]
Tongan_i = dat_Tongan[dat_Tongan$tokenPooled == "i" & dat_Tongan$speech_prec_pooled == "coronals" & dat_Tongan$speech_fol_pooled == "coronals",]
NZE_DRESS = dat_NZE[dat_NZE$tokenPooled == "e" & dat_NZE$speech_prec_pooled == "coronals" & dat_NZE$speech_fol_pooled == "coronals",]
Tongan_e = dat_Tongan[dat_Tongan$tokenPooled == "e" & dat_Tongan$speech_prec_pooled == "coronals" & dat_Tongan$speech_fol_pooled == "coronals",]
NZE_START = dat_NZE[dat_NZE$tokenPooled == "ɐː" & dat_NZE$speech_prec_pooled == "coronals" & dat_NZE$speech_fol_pooled == "coronals",]
Tongan_a = dat_Tongan[dat_Tongan$tokenPooled == "a" & dat_Tongan$speech_prec_pooled == "coronals" & dat_Tongan$speech_fol_pooled == "coronals",]
NZE_THOUGHT = dat_NZE[dat_NZE$tokenPooled == "oː" & dat_NZE$speech_prec_pooled == "coronals" & dat_NZE$speech_fol_pooled == "coronals",]
Tongan_o = dat_Tongan[dat_Tongan$tokenPooled == "o" & dat_Tongan$speech_prec_pooled == "coronals" & dat_Tongan$speech_fol_pooled == "coronals",]
# estimate smooths using R's generic predict.smooth.spline function
smooth_NZE_FLEECE=list(theta=seq(min(NZE_FLEECE$theta_uncut_z)*180/pi, 
                                 max(NZE_FLEECE$theta_uncut_z)*180/pi, length=100), 
                       r=predict(smooth.spline(NZE_FLEECE$theta_uncut_z, NZE_FLEECE$predicted_values), 
                                 seq(min(NZE_FLEECE$theta_uncut_z), max(NZE_FLEECE$theta_uncut_z), 
                                     length=100))$y, line=list(color="ORANGE0", dash="dash"))
smooth_Tongan_i=list(theta=seq(min(Tongan_i$theta_uncut_z)*180/pi, 
                               max(Tongan_i$theta_uncut_z)*180/pi, length=100), 
                     r=predict(smooth.spline(Tongan_i$theta_uncut_z, Tongan_i$predicted_values), 
                               seq(min(Tongan_i$theta_uncut_z), max(Tongan_i$theta_uncut_z), 
                                   length=100))$y, line=list(color="ORANGE0", dash=""))
smooth_NZE_DRESS=list(theta=seq(min(NZE_DRESS$theta_uncut_z)*180/pi, 
                                 max(NZE_DRESS$theta_uncut_z)*180/pi, length=100), 
                       r=predict(smooth.spline(NZE_DRESS$theta_uncut_z, NZE_DRESS$predicted_values), 
                                 seq(min(NZE_DRESS$theta_uncut_z), max(NZE_DRESS$theta_uncut_z), 
                                     length=100))$y, line=list(color="dark_blue", dash="dash"))
smooth_Tongan_e=list(theta=seq(min(Tongan_e$theta_uncut_z)*180/pi, 
                               max(Tongan_e$theta_uncut_z)*180/pi, length=100), 
                     r=predict(smooth.spline(Tongan_e$theta_uncut_z, Tongan_e$predicted_values), 
                               seq(min(Tongan_e$theta_uncut_z), max(Tongan_e$theta_uncut_z), 
                                   length=100))$y, line=list(color="dark_blue", dash=""))
smooth_NZE_START=list(theta=seq(min(NZE_START$theta_uncut_z)*180/pi, 
                                 max(NZE_START$theta_uncut_z)*180/pi, length=100), 
                       r=predict(smooth.spline(NZE_START$theta_uncut_z, NZE_START$predicted_values), 
                                 seq(min(NZE_START$theta_uncut_z), max(NZE_START$theta_uncut_z), 
                                     length=100))$y, line=list(color="RED0", dash="dash"))
smooth_Tongan_a=list(theta=seq(min(Tongan_a$theta_uncut_z)*180/pi, 
                               max(Tongan_a$theta_uncut_z)*180/pi, length=100), 
                     r=predict(smooth.spline(Tongan_a$theta_uncut_z, Tongan_a$predicted_values), 
                               seq(min(Tongan_a$theta_uncut_z), max(Tongan_a$theta_uncut_z), 
                                   length=100))$y, line=list(color="RED0", dash=""))
smooth_NZE_THOUGHT=list(theta=seq(min(NZE_THOUGHT$theta_uncut_z)*180/pi, 
                                 max(NZE_THOUGHT$theta_uncut_z)*180/pi, length=100), 
                       r=predict(smooth.spline(NZE_THOUGHT$theta_uncut_z, 
                                               NZE_THOUGHT$predicted_values), 
                                 seq(min(NZE_THOUGHT$theta_uncut_z), max(NZE_THOUGHT$theta_uncut_z), 
                                     length=100))$y, line=list(color="pink", dash="dash"))
smooth_Tongan_o=list(theta=seq(min(Tongan_o$theta_uncut_z)*180/pi, 
                               max(Tongan_o$theta_uncut_z)*180/pi, length=100), 
                     r=predict(smooth.spline(Tongan_o$theta_uncut_z, Tongan_o$predicted_values), 
                               seq(min(Tongan_o$theta_uncut_z), max(Tongan_o$theta_uncut_z), 
                                   length=100))$y, line=list(color="pink", dash=""))
# set Rho max to the max of the predicted_values + 5
max_predictions = max(max(smooth_NZE_FLEECE$r), max(smooth_NZE_DRESS$r), max(smooth_NZE_START$r), 
                      max(smooth_NZE_THOUGHT$r), max(smooth_Tongan_i$r), max(smooth_Tongan_e$r), 
                      max(smooth_Tongan_a$r), max(smooth_Tongan_o$r))
maximum=max_predictions+5
rm(max_predictions)
# colors from smooths don't get passed on correctly -> specify again
colors = c(ORANGE0, ORANGE0, dark_blue, dark_blue, RED0, RED0, pink, pink)
p = plot_ly(type='scatterpolar', mode='lines') %>% 
  add_trace(theta=smooth_NZE_FLEECE$theta, r=smooth_NZE_FLEECE$r, line=list(color=colors[1], width=2.5,dash=smooth_NZE_FLEECE$line$dash[[1]]), name="FLEECE /iː/ NZE") %>% 
  add_trace(theta=smooth_Tongan_i$theta, r=smooth_Tongan_i$r, line=list(color=colors[2], width=2.5, dash=smooth_Tongan_i$line$dash[[1]]), name="/i/ Tongan") %>%
  add_trace(theta=smooth_NZE_DRESS$theta, r=smooth_NZE_DRESS$r, line=list(color=colors[3], width=2.5, dash=smooth_NZE_DRESS$line$dash[[1]]), name="DRESS /e/ NZE") %>% 
  add_trace(theta=smooth_Tongan_e$theta, r=smooth_Tongan_e$r, line=list(color=colors[4], width=2.5, dash=smooth_Tongan_e$line$dash[[1]]), name="/e/ Tongan") %>%
  add_trace(theta=smooth_NZE_START$theta, r=smooth_NZE_START$r, line=list(color=colors[5], width=2.5, dash=smooth_NZE_START$line$dash[[1]]), name="START /iː/ NZE") %>% 
  add_trace(theta=smooth_Tongan_a$theta, r=smooth_Tongan_a$r, line=list(color=colors[6], width=2.5, dash=smooth_Tongan_a$line$dash[[1]]), name="/a/ Tongan") %>%
  add_trace(theta=smooth_NZE_THOUGHT$theta, r=smooth_NZE_THOUGHT$r, line=list(color=colors[7], width=2.5, dash=smooth_NZE_THOUGHT$line$dash[[1]]), name="THOUGHT /oː/ NZE") %>% 
  add_trace(theta=smooth_Tongan_o$theta, r=smooth_Tongan_o$r, line=list(color=colors[8], width=2.5, dash=smooth_Tongan_o$line$dash[[1]]), name="/o/ Tongan") %>%
  layout(polar=list(sector=c(20,160), radialaxis=list(angle=90, range=c(0,maximum)),  
                    angularaxis=list(thetaunit='radians', direction="clockwise", rotation=0)), 
         title="Tongan & NZE 'cardinal vowels' flanked by coronal sounds", 
         legend=list(orientation="h", xanchor="center", x=0.5,y=0.012))
p

if(printPDF==TRUE)
{
  orca(p, "Figure10.pdf",format="pdf")
  orca(p, "Figure10.jpg",format="jpeg")
}
rm(dat_NZE, dat_Tongan, NZE_FLEECE, NZE_DRESS, NZE_START, NZE_THOUGHT, smooth_NZE_FLEECE,smooth_NZE_DRESS, smooth_NZE_START, smooth_NZE_THOUGHT, smooth_Tongan_i, smooth_Tongan_e, smooth_Tongan_a, smooth_Tongan_o, maximum)
LS0tCnRpdGxlOiAiR0FNTXMgYW5hbHlzZXMgVHJvbWJvbmUgLSBUb25nYW4gdnMgRW5nbGlzaCAoTlpFKSAtPiBwYXBlciBwbG90cyIKYXV0aG9yOgotIEphbGFsIEFsLVRhbWltaSAoTmV3Y2FzdGxlIFVuaXZlcnNpdHkpCi0gRG9uYWxkIERlcnJpY2sgKFVuaXZlcnNpdHkgb2YgQ2FudGVyYnVyeSkKLSBNYXR0aGlhcyBIZXluZSAoQm9zdG9uIFVuaXZlcnNpdHkpCmRhdGU6ICJgciBmb3JtYXQoU3lzLnRpbWUoKSwgJyVkICVCICVZJylgIgpvdXRwdXQ6CiAgaHRtbF9ub3RlYm9vazoKICAgIG51bWJlcl9zZWN0aW9uczogeWVzCiAgICB0b2M6IHllcwogICAgdG9jX2RlcHRoOiA2CiAgICB0b2NfZmxvYXQ6CiAgICAgIGNvbGxhcHNlZDogeWVzCiAgd29yZF9kb2N1bWVudDoKICAgIHRvYzogeWVzCiAgICB0b2NfZGVwdGg6ICc2JwogIHBkZl9kb2N1bWVudDoKICAgIHRvYzogeWVzCiAgICB0b2NfZGVwdGg6ICc2JwogIGh0bWxfZG9jdW1lbnQ6CiAgICB0b2M6IHllcwogICAgdG9jX2RlcHRoOiAnNicKLS0tCgpUaGlzIG5vdGVib29rIHByb3ZpZGVzIHRoZSBwbG90cyBmb3IgdGhlIGFydGljbGU6IEhleW5lLCBNLiwgRGVycmljaywgRC4sIGFuZCBBbC1UYW1pbWksIEouICh1bmRlciByZXZpZXcpLiAiTmF0aXZlIGxhbmd1YWdlIGluZmx1ZW5jZSBvbiBicmFzcyBpbnN0cnVtZW50IHBlcmZvcm1hbmNlOiBBbiBhcHBsaWNhdGlvbiBvZiBnZW5lcmFsaXplZCBhZGRpdGl2ZSBtaXhlZCBtb2RlbHMgKEdBTU1zKSB0byBtaWRzYWdpdHRhbCB1bHRyYXNvdW5kIGltYWdlcyBvZiB0aGUgdG9uZ3VlIi4gRnJvbnRpZXJzIFJlc2VhcmNoIFRvcGljOiBNb2RlbHMgYW5kIFRoZW9yaWVzIG9mIFNwZWVjaCBQcm9kdWN0aW9uLiBFZC4gQWRhbWFudGlvcyBHYWZvcyAmIFBhc2NhbCB2YW4gTGllc2hvdXQuCgoKIyBMb2FkaW5nIHBhY2thZ2VzCgpgYGB7ciB3YXJuaW5nPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCBlcnJvcj1GQUxTRX0KbG9hZF9wYWNrYWdlcyA9IGMoInJlYWRyIiwia25pdHIiLCJnZ3Bsb3QyIiwibWdjdiIsIml0c2FkdWciLCJwYXJhbGxlbCIsImRwbHlyIiwicmxpc3QiLCJwbG90bHkiKQojIGRwbHlyLCBybGlzdCwgYW5kIHBsb3RseSBhcmUgcmVxdWlyZWQgYnkgdGhlIGN1c3RvbSBwbG90dGluZyBmdW5jdGlvbnMKZm9yKHBrZyBpbiBsb2FkX3BhY2thZ2VzKXsKICBldmFsKGJxdW90ZShsaWJyYXJ5KC4ocGtnKSkpKQogIGlmIChwYXN0ZTAoInBhY2thZ2U6IiwgcGtnKSAlaW4lIHNlYXJjaCgpKXsKICAgIGNhdChwYXN0ZTAoIlN1Y2Nlc3NmdWxseSBsb2FkZWQgdGhlICIsIHBrZywgIiBwYWNrYWdlLlxuIikpCiAgfWVsc2V7CiAgICBpbnN0YWxsLnBhY2thZ2VzKHBrZykKICAgIGV2YWwoYnF1b3RlKGxpYnJhcnkoLihwa2cpKSkpCiAgICBpZiAocGFzdGUwKCJwYWNrYWdlOiIsIHBrZykgJWluJSBzZWFyY2goKSl7CiAgICAgIGNhdChwYXN0ZTAoIlN1Y2Nlc3NmdWxseSBsb2FkZWQgdGhlICIsIHBrZywgIiBwYWNrYWdlLlxuIikpCiAgICB9CiAgfQp9CnJtKGxvYWRfcGFja2FnZXMsIHBrZykKU3lzLnNldGVudignTUFQQk9YX1RPS0VOJyA9ICdzay5leUoxSWpvaVpHUmxjbkpwWTJzaUxDSmhJam9pWTJwMk1XMW5kbk5vTVhjellUUmtiWGQ2ZHpSdU1UUTJhQ0o5LlVUYWk0d1djRkZWYUpBdU9yQVg3VlEnKQoKIyBkZWNpZGUgd2hldGhlciB0byBzYXZlIHBsb3RzIGFzIFBERiBhbmQganBnIGZpbGVzIHVzaW5nIHRoZSBPcmNhIGNvbW1hbmQgbGluZSB1dGlsaXR5CnNhdmU9RkFMU0UKcHJpbnRQREY9RkFMU0UKYGBgCgojIyBMb2FkaW5nIGN1c3RvbSBwbG90dGluZyBmdW5jdGlvbnMKCiMjIyBwbG90bHlfbW9kZWxfb3V0cHV0cyBmdW5jdGlvbiAoTWF0dGhpYXMgSGV5bmUsIDIwMTkpCgpgYGB7ciB3YXJuaW5nPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCBlcnJvcj1GQUxTRX0KIyBwbG90IG11bHRpcGxlIEdBTSBtb2RlbCBvdXRwdXRzCnBsb3RseV9tb2RlbF9vdXRwdXRzIDwtIGZ1bmN0aW9uKG1vZGVsLCBjaGFuZ2luZ19jb25kLCBjaGFuZ2luZ192YXIsIGNvbnN0YW50X2NvbmQxLCBjb25zdGFudF92YXIxLCB2YWx1ZXMsIGNvbnN0YW50X2NvbmQyPU5VTEwsIGNvbnN0YW50X3ZhcjI9TlVMTCwgcHJpbnQ9VFJVRSl7CiAgaWYobGVuZ3RoKGNvbnN0YW50X3ZhcjEpPjEgfCBsZW5ndGgoY29uc3RhbnRfdmFyMik+MSl7CiAgICBwcmludCgiRXJyb3I6IENvbnN0YW50IHZhcmlhYmxlcyBjYW4gb25seSBoYXZlIGxlbmd0aCAxLiIpCiAgfWVsc2V7CiAgICBpZighaXMubnVsbChjb25zdGFudF9jb25kMikgJiYgIWlzLm51bGwoY29uc3RhbnRfdmFyMikgJiYgbGVuZ3RoKGNoYW5naW5nX3Zhcik9PTIpewogICAgICAjIHdvcmtzIGZvciBtb2RlbHMgTm90ZXMuZ2FtLi4uCiAgICAgIGNvbmRfcDEgPSBjYXB0dXJlLm91dHB1dChjYXQocGFzdGUwKCJsaXN0KCIsIGNoYW5naW5nX2NvbmQsICI9JyIsIGNoYW5naW5nX3ZhclsxXSwgIicsICIsIGNvbnN0YW50X2NvbmQxLCAiPSciLCBjb25zdGFudF92YXIxLCAiJywgIiwgY29uc3RhbnRfY29uZDIsICI9JyIsIGNvbnN0YW50X3ZhcjIsICInKSIpKSkKICAgICAgcDE9cGxvdF9zbW9vdGgoeD1nZXQobW9kZWwpLCB2aWV3PXZhbHVlcywgY29uZCA9IGV2YWwocGFyc2UodGV4dD1jb25kX3AxKSkpCiAgICAgIGNvbmRfcDIgPSBjYXB0dXJlLm91dHB1dChjYXQocGFzdGUwKCJsaXN0KCIsIGNoYW5naW5nX2NvbmQsICI9JyIsIGNoYW5naW5nX3ZhclsyXSwgIicsICIsIGNvbnN0YW50X2NvbmQxLCAiPSciLCBjb25zdGFudF92YXIxLCAiJywgIiwgY29uc3RhbnRfY29uZDIsICI9JyIsIGNvbnN0YW50X3ZhcjIsICInKSIpKSkKICAgICAgcDI9cGxvdF9zbW9vdGgoeD1nZXQobW9kZWwpLCB2aWV3PXZhbHVlcywgY29uZCA9IGV2YWwocGFyc2UodGV4dD1jb25kX3AyKSkpCiAgICAgIAogICAgICAjIHNldCBSaG8gbWF4IHRvIHRoZSBtYXggb2YgdGhlIGZpdCArIGhhbGYgdGhlIGRpZmZlcmVuY2UgYmV0d2VlbiBtYXggb2YgdGhlIGZpdCBhbmQgdGhlIHVwcGVyIGxpbWl0CiAgICAgICMgbWF4X3VsID0gbWF4KHAxJGZ2JHVsLCBwMiRmdiR1bCkKICAgICAgIyBtYXhfZml0ID0gbWF4KHAxJGZ2JGZpdCwgcDIkZnYkZml0KQogICAgICAjIG1heGltdW0gPSBtYXhfZml0KygobWF4X3VsLW1heF9maXQpLzIpCiAgICAgIG1heGltdW0gPSBtYXgocDEkZnYkdWwsIHAyJGZ2JHVsKQogICAgICAKICAgICAgIyBwbG90IGluIHBvbGFyIGNvb3JkaW5hdGVzCiAgICAgIHA9cGxvdF9seSh0eXBlPSdzY2F0dGVycG9sYXInLCBtb2RlPSdsaW5lcycpICU+JSAKICAgICAgICBhZGRfdHJhY2UodGhldGE9cDEkZnYkdGhldGFfdW5jdXRfeioxODAvcGksIHI9cDEkZnYkZml0LCBsaW5lPWxpc3QoY29sb3I9ImJsdWUiLCBkYXNoPSJkYXNoIiwgd2lkdGg9Mi41KSwgbmFtZT1jaGFuZ2luZ192YXJbMV0pICU+JSAKICAgICAgICBhZGRfdHJhY2UodGhldGE9cDEkZnYkdGhldGFfdW5jdXRfeioxODAvcGksIHI9cDEkZnYkdWwsIGxpbmU9bGlzdChjb2xvcj0iYmx1ZSIsIGRhc2g9ImRhc2giLCB3aWR0aD0wLjUpLCBzaG93bGVnZW5kPUZBTFNFKSAlPiUgCiAgICAgICAgYWRkX3RyYWNlKHRoZXRhPXAxJGZ2JHRoZXRhX3VuY3V0X3oqMTgwL3BpLCByPXAxJGZ2JGxsLCBsaW5lPWxpc3QoY29sb3I9ImJsdWUiLCBkYXNoPSJkYXNoIiwgd2lkdGg9MC41KSwgc2hvd2xlZ2VuZD1GQUxTRSkgJT4lIAogICAgICAgIGFkZF90cmFjZSh0aGV0YT1wMiRmdiR0aGV0YV91bmN1dF96KjE4MC9waSwgcj1wMiRmdiRmaXQsIGxpbmU9bGlzdChjb2xvcj0icmVkIiwgd2lkdGg9Mi41KSwgbmFtZT1jaGFuZ2luZ192YXJbMl0pICU+JSAKICAgICAgICBhZGRfdHJhY2UodGhldGE9cDIkZnYkdGhldGFfdW5jdXRfeioxODAvcGksIHI9cDIkZnYkdWwsIGxpbmU9bGlzdChjb2xvcj0icmVkIiwgZGFzaD0iZG90Iiwgd2lkdGg9MC41KSwgc2hvd2xlZ2VuZD1GQUxTRSkgJT4lIAogICAgICAgIGFkZF90cmFjZSh0aGV0YT1wMiRmdiR0aGV0YV91bmN1dF96KjE4MC9waSwgcj1wMiRmdiRsbCwgbGluZT1saXN0KGNvbG9yPSJyZWQiLCBkYXNoPSJkb3QiLCB3aWR0aD0wLjUpLCBzaG93bGVnZW5kPUZBTFNFKSAlPiUKICAgICAgICBsYXlvdXQocG9sYXI9bGlzdChzZWN0b3I9YygyMCwxNjApLCByYWRpYWxheGlzPWxpc3QoYW5nbGU9OTAsIHJhbmdlPWMoMCxtYXhpbXVtKSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgYW5ndWxhcmF4aXM9bGlzdCh0aGV0YXVuaXQ9J3JhZGlhbnMnLCBkaXJlY3Rpb249ImNsb2Nrd2lzZSIsIHJvdGF0aW9uPTApKSwgCiAgICAgICAgICAgICAgIHRpdGxlPXBhc3RlMCgiR0FNIHNtb290aHMgQCIsIGNvbnN0YW50X3ZhcjEsICIgJiAiLCBjb25zdGFudF92YXIyKSwgCiAgICAgICAgICAgICAgIGxlZ2VuZD1saXN0KG9yaWVudGF0aW9uPSJoIiwgeGFuY2hvcj0iY2VudGVyIiwgeD0wLjUseT0wLjAxMikpCiAgICAgIHAKICAgIH1lbHNlIGlmKGlzLm51bGwoY29uc3RhbnRfY29uZDIpICYmIGlzLm51bGwoY29uc3RhbnRfdmFyMikgJiYgbGVuZ3RoKGNoYW5naW5nX3Zhcik9PTIpewogICAgICAjIG5vIHNwZWNpZmljIGNhc2UgeWV0CiAgICAgIGNvbmRfcDEgPSBjYXB0dXJlLm91dHB1dChjYXQocGFzdGUwKCJsaXN0KCIsIGNoYW5naW5nX2NvbmQsICI9JyIsIGNoYW5naW5nX3ZhclsxXSwgIicsICIsIGNvbnN0YW50X2NvbmQxLCAiPSciLCBjb25zdGFudF92YXIxLCAiJykiKSkpCiAgICAgIHAxPXBsb3Rfc21vb3RoKHg9Z2V0KG1vZGVsKSwgdmlldz12YWx1ZXMsIGNvbmQgPSBldmFsKHBhcnNlKHRleHQ9Y29uZF9wMSkpKQogICAgICBjb25kX3AyID0gY2FwdHVyZS5vdXRwdXQoY2F0KHBhc3RlMCgibGlzdCgiLCBjaGFuZ2luZ19jb25kLCAiPSciLCBjaGFuZ2luZ192YXJbMl0sICInLCAiLCBjb25zdGFudF9jb25kMSwgIj0nIiwgY29uc3RhbnRfdmFyMSwgIicpIikpKQogICAgICBwMj1wbG90X3Ntb290aCh4PWdldChtb2RlbCksIHZpZXc9dmFsdWVzLCBjb25kID0gZXZhbChwYXJzZSh0ZXh0PWNvbmRfcDIpKSkKICAgICAgCiAgICAgICMgc2V0IFJobyBtYXggdG8gdGhlIG1heCBvZiB0aGUgZml0ICsgaGFsZiB0aGUgZGlmZmVyZW5jZSBiZXR3ZWVuIG1heCBvZiB0aGUgZml0IGFuZCB0aGUgdXBwZXIgbGltaXQKICAgICAgIyBtYXhfdWwgPSBtYXgocDEkZnYkdWwsIHAyJGZ2JHVsKQogICAgICAjIG1heF9maXQgPSBtYXgocDEkZnYkZml0LCBwMiRmdiRmaXQpCiAgICAgICMgbWF4aW11bSA9IG1heF9maXQrKChtYXhfdWwtbWF4X2ZpdCkvMikKICAgICAgbWF4aW11bSA9IG1heChwMSRmdiR1bCwgcDIkZnYkdWwpCiAgICAgIAogICAgICAjIHBsb3QgaW4gcG9sYXIgY29vcmRpbmF0ZXMKICAgICAgcD1wbG90X2x5KHR5cGU9J3NjYXR0ZXJwb2xhcicsIG1vZGU9J2xpbmVzJykgJT4lIAogICAgICAgIGFkZF90cmFjZSh0aGV0YT1wMSRmdiR0aGV0YV91bmN1dF96KjE4MC9waSwgcj1wMSRmdiRmaXQsIGxpbmU9bGlzdChjb2xvcj0iYmx1ZSIsIGRhc2g9ImRhc2giLCB3aWR0aD0yLjUpLCBuYW1lPWNoYW5naW5nX3ZhclsxXSkgJT4lIAogICAgICAgIGFkZF90cmFjZSh0aGV0YT1wMSRmdiR0aGV0YV91bmN1dF96KjE4MC9waSwgcj1wMSRmdiR1bCwgbGluZT1saXN0KGNvbG9yPSJibHVlIiwgZGFzaD0iZGFzaCIsIHdpZHRoPTAuNSksIHNob3dsZWdlbmQ9RkFMU0UpICU+JSAKICAgICAgICBhZGRfdHJhY2UodGhldGE9cDEkZnYkdGhldGFfdW5jdXRfeioxODAvcGksIHI9cDEkZnYkbGwsIGxpbmU9bGlzdChjb2xvcj0iYmx1ZSIsIGRhc2g9ImRhc2giLCB3aWR0aD0wLjUpLCBzaG93bGVnZW5kPUZBTFNFKSAlPiUgCiAgICAgICAgYWRkX3RyYWNlKHRoZXRhPXAyJGZ2JHRoZXRhX3VuY3V0X3oqMTgwL3BpLCByPXAyJGZ2JGZpdCwgbGluZT1saXN0KGNvbG9yPSJyZWQiLCB3aWR0aD0yLjUpLCBuYW1lPWNoYW5naW5nX3ZhclsyXSkgJT4lIAogICAgICAgIGFkZF90cmFjZSh0aGV0YT1wMiRmdiR0aGV0YV91bmN1dF96KjE4MC9waSwgcj1wMiRmdiR1bCwgbGluZT1saXN0KGNvbG9yPSJyZWQiLCBkYXNoPSJkb3QiLCB3aWR0aD0wLjUpLCBzaG93bGVnZW5kPUZBTFNFKSAlPiUgCiAgICAgICAgYWRkX3RyYWNlKHRoZXRhPXAyJGZ2JHRoZXRhX3VuY3V0X3oqMTgwL3BpLCByPXAyJGZ2JGxsLCBsaW5lPWxpc3QoY29sb3I9InJlZCIsIGRhc2g9ImRvdCIsIHdpZHRoPTAuNSksIHNob3dsZWdlbmQ9RkFMU0UpICU+JQogICAgICAgIGxheW91dChwb2xhcj1saXN0KHNlY3Rvcj1jKDIwLDE2MCksIHJhZGlhbGF4aXM9bGlzdChhbmdsZT05MCwgcmFuZ2U9YygwLG1heGltdW0pKSwKICAgICAgICAgICAgICAgICAgICAgICAgICBhbmd1bGFyYXhpcz1saXN0KHRoZXRhdW5pdD0ncmFkaWFucycsIGRpcmVjdGlvbj0iY2xvY2t3aXNlIiwgcm90YXRpb249MCkpLCAKICAgICAgICAgICAgICAgdGl0bGU9cGFzdGUwKCJHQU0gc21vb3RocyBAIiwgY29uc3RhbnRfdmFyMSwgIiAmICIsIGNvbnN0YW50X3ZhcjIpLCAKICAgICAgICAgICAgICAgbGVnZW5kPWxpc3Qob3JpZW50YXRpb249ImgiLCB4YW5jaG9yPSJjZW50ZXIiLCB4PTAuNSx5PTAuMDEyKSkKICAgICAgcAogICAgfWVsc2UgaWYoaXMubnVsbChjb25zdGFudF9jb25kMikgJiYgaXMubnVsbChjb25zdGFudF92YXIyKSAmJiBsZW5ndGgoY2hhbmdpbmdfdmFyKT4yKXsKICAgICAgIyB3b3JrcyBmb3IgbW9kZWxzIE5aRS5nYW0uLi4gb3IgVG9uZ2FuLmdhbS4uLgogICAgICBmb3IgKGkgaW4gMTpsZW5ndGgoY2hhbmdpbmdfdmFyKSl7CiAgICAgICAgaWYoY2hhbmdpbmdfY29uZCA9PSBjb25zdGFudF9jb25kMSl7CiAgICAgICAgICBjb25kX3AxID0gY2FwdHVyZS5vdXRwdXQoY2F0KHBhc3RlMCgibGlzdCgiLCBjb25zdGFudF9jb25kMSwgIj0nIiwgY29uc3RhbnRfdmFyMSwgIicpIikpKQogICAgICAgICAgcDE9cGxvdF9zbW9vdGgoeD1nZXQobW9kZWwpLCB2aWV3PXZhbHVlcywgY29uZCA9IGV2YWwocGFyc2UodGV4dD1jb25kX3AxKSkpCiAgICAgICAgICAjIGV4Y2VwdGlvbiBmb3IgS0lUICg9J1xcXFwnKSB3aGVuIG5vdCB1c2luZyBJUEEgc3ltYm9scwogICAgICAgICAgaWYgKGNoYW5naW5nX3ZhcltpXSE9IlxcXFwiKXsKICAgICAgICAgICAgY29uZF9wMiA9IGNhcHR1cmUub3V0cHV0KGNhdChwYXN0ZTAoImxpc3QoIiwgY2hhbmdpbmdfY29uZCwgIj0nIiwgY2hhbmdpbmdfdmFyW2ldLCAiJykiKSkpCiAgICAgICAgICAgIHAyPXBsb3Rfc21vb3RoKHg9Z2V0KG1vZGVsKSwgdmlldz12YWx1ZXMsIGNvbmQgPSBldmFsKHBhcnNlKHRleHQ9Y29uZF9wMikpKQogICAgICAgICAgfWVsc2V7CiAgICAgICAgICAgIHAyPXBsb3Rfc21vb3RoKHg9Z2V0KG1vZGVsKSwgdmlldz12YWx1ZXMsIGNvbmQgPSBsaXN0KHRva2VuLm9yZD0nXFxcXCcpKQogICAgICAgICAgfQogICAgICAgICAgCiAgICAgICAgICAjIHNldCBSaG8gbWF4IHRvIHRoZSBtYXggb2YgdGhlIGZpdCArIGhhbGYgdGhlIGRpZmZlcmVuY2UgYmV0d2VlbiBtYXggb2YgdGhlIGZpdCBhbmQgdGhlIHVwcGVyIGxpbWl0CiAgICAgICAgICAjIG1heF91bCA9IG1heChwMSRmdiR1bCwgcDIkZnYkdWwpCiAgICAgICAgICAjIG1heF9maXQgPSBtYXgocDEkZnYkZml0LCBwMiRmdiRmaXQpCiAgICAgICAgICAjIG1heGltdW0gPSBtYXhfZml0KygobWF4X3VsLW1heF9maXQpLzIpCiAgICAgICAgICBtYXhpbXVtID0gbWF4KHAxJGZ2JHVsLCBwMiRmdiR1bCkKCiAgICAgICAgICAjIHBsb3QgaW4gcG9sYXIgY29vcmRpbmF0ZXMKICAgICAgICAgIHA9cGxvdF9seSh0eXBlPSdzY2F0dGVycG9sYXInLCBtb2RlPSdsaW5lcycpICU+JSAKICAgICAgICAgICAgYWRkX3RyYWNlKHRoZXRhPXAxJGZ2JHRoZXRhX3VuY3V0X3oqMTgwL3BpLCByPXAxJGZ2JGZpdCwgbGluZT1saXN0KGNvbG9yPSJibHVlIiwgZGFzaD0iZGFzaCIsIHdpZHRoPTIuNSksIG5hbWU9Y29uc3RhbnRfdmFyMSkgJT4lIAogICAgICAgICAgICBhZGRfdHJhY2UodGhldGE9cDEkZnYkdGhldGFfdW5jdXRfeioxODAvcGksIHI9cDEkZnYkdWwsIGxpbmU9bGlzdChjb2xvcj0iYmx1ZSIsIGRhc2g9ImRhc2giLCB3aWR0aD0wLjUpLCBzaG93bGVnZW5kPUZBTFNFKSAlPiUgCiAgICAgICAgICAgIGFkZF90cmFjZSh0aGV0YT1wMSRmdiR0aGV0YV91bmN1dF96KjE4MC9waSwgcj1wMSRmdiRsbCwgbGluZT1saXN0KGNvbG9yPSJibHVlIiwgZGFzaD0iZGFzaCIsIHdpZHRoPTAuNSksIHNob3dsZWdlbmQ9RkFMU0UpICU+JSAKICAgICAgICAgICAgYWRkX3RyYWNlKHRoZXRhPXAyJGZ2JHRoZXRhX3VuY3V0X3oqMTgwL3BpLCByPXAyJGZ2JGZpdCwgbGluZT1saXN0KGNvbG9yPSJyZWQiLCB3aWR0aD0yLjUpLCBuYW1lPWNoYW5naW5nX3ZhcltpXSkgJT4lIAogICAgICAgICAgICBhZGRfdHJhY2UodGhldGE9cDIkZnYkdGhldGFfdW5jdXRfeioxODAvcGksIHI9cDIkZnYkdWwsIGxpbmU9bGlzdChjb2xvcj0icmVkIiwgZGFzaD0iZG90Iiwgd2lkdGg9MC41KSwgc2hvd2xlZ2VuZD1GQUxTRSkgJT4lIAogICAgICAgICAgICBhZGRfdHJhY2UodGhldGE9cDIkZnYkdGhldGFfdW5jdXRfeioxODAvcGksIHI9cDIkZnYkbGwsIGxpbmU9bGlzdChjb2xvcj0icmVkIiwgZGFzaD0iZG90Iiwgd2lkdGg9MC41KSwgc2hvd2xlZ2VuZD1GQUxTRSkgJT4lCiAgICAgICAgICAgIGxheW91dChwb2xhcj1saXN0KHNlY3Rvcj1jKDIwLDE2MCksIHJhZGlhbGF4aXM9bGlzdChhbmdsZT05MCwgcmFuZ2U9YygwLG1heGltdW0pKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYW5ndWxhcmF4aXM9bGlzdCh0aGV0YXVuaXQ9J3JhZGlhbnMnLCBkaXJlY3Rpb249ImNsb2Nrd2lzZSIsIHJvdGF0aW9uPTApKSwgCiAgICAgICAgICAgICAgICAgICB0aXRsZT1wYXN0ZTAoIkdBTSBzbW9vdGhzICIsY29uc3RhbnRfdmFyMSwiIHZzICIsIGNoYW5naW5nX3ZhcltpXSksIAogICAgICAgICAgICAgICAgICAgbGVnZW5kPWxpc3Qob3JpZW50YXRpb249ImgiLCB4YW5jaG9yPSJjZW50ZXIiLCB4PTAuNSx5PTAuMDEyKSkKICAgICAgICAgIFN5cy5zbGVlcCgwKQogICAgICAgICAgcHJpbnQocCkKICAgICAgICB9CiAgICAgIH0KICAgIH0KICB9Cn0KYGBgCgojIyMgcGxvdGx5X3NpZ19kaWZmX25vdGVzIGZ1bmN0aW9uIChNYXR0aGlhcyBIZXluZSwgMjAxOSkgLT4gd2l0aCB1cGRhdGVkIGxlZ2VuZCBwb3NpdGlvbgoKYGBge3Igd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgZXJyb3I9RkFMU0V9CiMgcGxvdCBzbW9vdGhzIHdpdGggc2hhZGluZyB0byBpbmRpY2F0ZSBzaWduaWZpY2FudCBkaWZmZXJlbmNlcyAoTWF0dGhpYXMgSGV5bmUsIDIwMTkpCnBsb3RseV9zbW9vdGhzX3dfc2lnX2RpZmYgPC0gZnVuY3Rpb24obW9kZWwsIGNvbmRpdGlvbiwgdmFyMSwgdmFyMiwgdmFsdWVzLCBsYW5ndWFnZSwgZmlsZU5hbWUsIHByaW50PVRSVUUsIHNhdmU9VFJVRSl7CiAgIyBzcGVjaWZ5IHBhdGggZm9yIHNhdmluZyBwbG90cwogICMgcGxvdF9mb2xkZXIgPSAic2F2ZWRfcGxvdHMiCiAgIyBTeXMuc2V0ZW52KE1BUEJPWF9UT0tFTiA9IDExMTIyMjIzMzMzNDQ0KQogICMgZ2V0IGludGVydmFscyBvZiBzaWduaWZpY2FudCBkaWZmZXJlbmNlcyBieSBydW5uaW5nIHBsb3RfZGlmZgogICMgdW5mb3J0dW5hdGVseSBzZXR0aW5nIHBsb3Q9RkFMU0UgZG9lc24ndCB3b3JrIGFzIGludGVydmFscyBvZiBzaWduaWZpY2FudCBkaWZmZXJlbmNlIGFyZSBub3QgZGlzcGxheWVkIQogICMgaGFyZGNvZGVkIGNvbmRpdGlvbgogICMgb3V0cHV0ID0gY2FwdHVyZS5vdXRwdXQocGxvdF9kaWZmKGdldChtb2RlbCksIHZpZXc9dmFsdWVzLCAKICAjICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb21wPWxpc3QodG9rZW5Qb29sZWQub3JkPWModmFyMSwgdmFyMikpKSkKICAjIG91dHB1dCA9IGNhcHR1cmUub3V0cHV0KHBsb3RfZGlmZihnZXQobW9kZWwpLCB2aWV3PXZhbHVlcywgY29tcD1saXN0KGxhbmdOb3RlSW50Lm9yZD1jKHBhc3RlMCgiVG9uZ2FuLiIsIG5vdGUsICIuIiwgaW50ZW5zaXR5KSwgcGFzdGUwKCJOWkUuIiwgbm90ZSwgIi4iLCBpbnRlbnNpdHkpKSkpKQogIG5hbWVzX3Ntb290aHM9bGlzdCgpCiAgaWYgKGNvbmRpdGlvbj09InRva2VuUG9vbGVkLm9yZCIgJiYgbGVuZ3RoKGxhbmd1YWdlKT09MSl7CiAgICBvdXRwdXRfY29tcCA9IGNhcHR1cmUub3V0cHV0KGNhdChwYXN0ZTAoImxpc3QoIiwgY29uZGl0aW9uLCAiPWModmFyMSwgdmFyMikpIikpKQogICAgbmFtZXNfc21vb3Roc1sxXT12YXIxCiAgICBuYW1lc19zbW9vdGhzWzJdPXZhcjIKICAgIHBsb3RfdGl0bGUgPSBwYXN0ZTAoIkdBTSBzbW9vdGhzICIsIGxhbmd1YWdlLCAiICIsIHZhcjEsICIgdnMgIiwgdmFyMikKICAgICMgcGxvdF9maWxlbmFtZSA9IHBhc3RlMChsYW5ndWFnZSwgIl8iLCB2YXIxLCAiX3ZzXyIsIHZhcjIsICJfZnJvbV8iLCBtb2RlbCkKICB9ZWxzZSBpZiAoY29uZGl0aW9uPT0ibGFuZ05vdGVJbnQub3JkIiAmJiBsZW5ndGgobGFuZ3VhZ2UpPT0yKXsKICAgIG91dHB1dF9jb21wID0gY2FwdHVyZS5vdXRwdXQoY2F0KHBhc3RlMCgibGlzdCgiLCBjb25kaXRpb24sICI9YygnIiwgbGFuZ3VhZ2VbMV0sICIuIiwgdmFyMSwgIi4iLCB2YXIyLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiJywgJyIsIGxhbmd1YWdlWzJdLCAiLiIsIHZhcjEsICIuIiwgdmFyMiwgIicpKSIpKSkKICAgIG5hbWVzX3Ntb290aHNbMV09cGFzdGUwKGxhbmd1YWdlWzFdLCAiLiIsIHZhcjEsICIuIiwgdmFyMikKICAgIG5hbWVzX3Ntb290aHNbMl09cGFzdGUwKGxhbmd1YWdlWzJdLCAiLiIsIHZhcjEsICIuIiwgdmFyMikKICAgIHBsb3RfdGl0bGUgPSBwYXN0ZTAoIkdBTSBzbW9vdGhzICIsIGxhbmd1YWdlWzFdLCAiLiIsIHZhcjEsICIuIiwgdmFyMiwgIiB2cyAiLCBsYW5ndWFnZVsyXSwgIi4iLCB2YXIxLCAiLiIsIHZhcjIpCiAgICAjIHBsb3RfZmlsZW5hbWUgPSBwYXN0ZTAobGFuZ3VhZ2VbMV0sICIuIiwgdmFyMSwgIi4iLCB2YXIyLCAiX3ZzXyIsIGxhbmd1YWdlWzJdLCAiLiIsIHZhcjEsICIuIiwgdmFyMiwgIl9mcm9tXyIsIG1vZGVsKQogIH1lbHNlIGlmIChjb25kaXRpb249PSJsYW5nTm90ZUludC5vcmQiICYmIGxlbmd0aChsYW5ndWFnZSk9PTEgJiYgbGVuZ3RoKHZhcjEpPT0yKXsKICAgIG91dHB1dF9jb21wID0gY2FwdHVyZS5vdXRwdXQoY2F0KHBhc3RlMCgibGlzdCgiLCBjb25kaXRpb24sICI9YygnIiwgbGFuZ3VhZ2UsICIuIiwgdmFyMVsxXSwgIi4iLCB2YXIyLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiJywgJyIsIGxhbmd1YWdlLCAiLiIsIHZhcjFbMl0sICIuIiwgdmFyMiwgIicpKSIpKSkKICAgIG5hbWVzX3Ntb290aHNbMV09cGFzdGUwKGxhbmd1YWdlLCAiLiIsIHZhcjFbMV0sICIuIiwgdmFyMikKICAgIG5hbWVzX3Ntb290aHNbMl09cGFzdGUwKGxhbmd1YWdlLCAiLiIsIHZhcjFbMl0sICIuIiwgdmFyMikKICAgIHBsb3RfdGl0bGUgPSBwYXN0ZTAoIkdBTSBzbW9vdGhzICIsIGxhbmd1YWdlLCAiLiIsIHZhcjFbMV0sICIuIiwgdmFyMiwgIiB2cyAiLCBsYW5ndWFnZSwgIi4iLCB2YXIxWzJdLCAiLiIsIHZhcjIpCiAgICAjIHBsb3RfZmlsZW5hbWUgPSBwYXN0ZTAobGFuZ3VhZ2UsICIuIiwgdmFyMVsxXSwgIi4iLCB2YXIyLCAiX3ZzXyIsIGxhbmd1YWdlLCAiLiIsIHZhcjFbMl0sICIuIiwgdmFyMiwgIl9mcm9tXyIsIG1vZGVsKQogIH0KICAjIG91dHB1dF9jb21wID0gY2FwdHVyZS5vdXRwdXQoY2F0KHBhc3RlMCgibGlzdCgiLCBjb25kaXRpb24sICI9Yyh2YXIxLCB2YXIyKSkiKSkpCiAgb3V0cHV0ID0gY2FwdHVyZS5vdXRwdXQocGxvdF9kaWZmKGdldChtb2RlbCksIHZpZXc9dmFsdWVzLCBjb21wPWV2YWwocGFyc2UodGV4dD1vdXRwdXRfY29tcCkpKSkKICAjIG5vIHNpZ25pZmljYW50IGRpZmZlcmVuY2UKICBpZiAoKGxlbmd0aChsYW5ndWFnZSk9PTEgJiYgbGVuZ3RoKHZhcjEpPT0xICYmIGxlbmd0aChvdXRwdXQpPT03KSB8IChsZW5ndGgobGFuZ3VhZ2UpPT0yICYmIGxlbmd0aChvdXRwdXQpPT02KSB8IAogICAgKGxlbmd0aChsYW5ndWFnZSk9PTEgJiYgbGVuZ3RoKHZhcjEpPT0yICYmIGxlbmd0aChvdXRwdXQpPT02KSl7CiAgICBpZiAobGVuZ3RoKHZhcjEpPT0xKXsKICAgICAgY2F0KHBhc3RlMCgiU21vb3RocyBmb3IgIiwgdmFyMSwgIiAmICIsIHZhcjIsICIgYXJlIG5vdCBzaWduaWZpY2FudGx5IGRpZmZlcmVudC5cbiIpKQogICAgICBkYXQxID0gTkEKICAgICAgYXNzaWduKHBhc3RlMCgiaW50X3NpZ19kaWZmXyIsIHZhcjEsICJfIiwgdmFyMiksIGRhdDEsIGVudmlyID0gLkdsb2JhbEVudikKICAgIH1lbHNlewogICAgICBjYXQocGFzdGUwKCJTbW9vdGhzIGZvciAiLCB2YXIxWzFdLCAiICYgIiwgdmFyMVsyXSwgIiBpbiAiLCBsYW5ndWFnZSwgIiBhcmUgbm90IHNpZ25pZmljYW50bHkgZGlmZmVyZW50LlxuIikpCiAgICAgIGRhdDEgPSBOQQogICAgICBhc3NpZ24ocGFzdGUwKCJpbnRfc2lnX2RpZmZfIiwgdmFyMVsxXSwgIl8iLCB2YXIxWzJdLCAiXyIsIHZhcjIsICJfIiwgbGFuZ3VhZ2UpLCBkYXQxLCBlbnZpciA9IC5HbG9iYWxFbnYpCiAgICB9CiAgICBybShkYXQxLCBvdXRwdXQpCiAgICAjIHJ1biBwbG90X3Ntb290aCB0byBncmFiIGRhdGEgZm9yIHBvbGFyIHBsb3RzCiAgICBpZiAoY29uZGl0aW9uPT0idG9rZW5Qb29sZWQub3JkIiAmJiBsZW5ndGgobGFuZ3VhZ2UpPT0xKXsKICAgICAgY29uZF9wMSA9IGNhcHR1cmUub3V0cHV0KGNhdChwYXN0ZTAoImxpc3QoIiwgY29uZGl0aW9uLCAiPXZhcjEpIikpKQogICAgICBjb25kX3AyID0gY2FwdHVyZS5vdXRwdXQoY2F0KHBhc3RlMCgibGlzdCgiLCBjb25kaXRpb24sICI9dmFyMikiKSkpCiAgICB9ZWxzZSBpZiAoY29uZGl0aW9uPT0ibGFuZ05vdGVJbnQub3JkIiAmJiBsZW5ndGgobGFuZ3VhZ2UpPT0yKXsKICAgICAgY29uZF9wMSA9IGNhcHR1cmUub3V0cHV0KGNhdChwYXN0ZTAoImxpc3QoIiwgY29uZGl0aW9uLCAiPSciLCBsYW5ndWFnZVsxXSwgIi4iLCB2YXIxLCAiLiIsIHZhcjIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiJywgIiwgY29uZGl0aW9uLCAiPSciLCBsYW5ndWFnZVsyXSwgIi4iLCB2YXIxLCAiLiIsIHZhcjIsICInKSIpKSkKICAgICAgY29uZF9wMiA9IGNhcHR1cmUub3V0cHV0KGNhdChwYXN0ZTAoImxpc3QoIiwgY29uZGl0aW9uLCAiPSciLCBsYW5ndWFnZVsyXSwgIi4iLCB2YXIxLCAiLiIsIHZhcjIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiJywgIiwgY29uZGl0aW9uLCAiPSciLCBsYW5ndWFnZVsxXSwgIi4iLCB2YXIxLCAiLiIsIHZhcjIsICInKSIpKSkKICAgIH1lbHNlIGlmIChjb25kaXRpb249PSJsYW5nTm90ZUludC5vcmQiICYmIGxlbmd0aChsYW5ndWFnZSk9PTEgJiYgbGVuZ3RoKHZhcjEpPT0yKXsKICAgICAgY29uZF9wMSA9IGNhcHR1cmUub3V0cHV0KGNhdChwYXN0ZTAoImxpc3QoIiwgY29uZGl0aW9uLCAiPSciLCBsYW5ndWFnZSwgIi4iLCB2YXIxWzFdLCAiLiIsIHZhcjIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiJywgIiwgY29uZGl0aW9uLCAiPSciLCBsYW5ndWFnZSwgIi4iLCB2YXIxWzJdLCAiLiIsIHZhcjIsICInKSIpKSkKICAgICAgY29uZF9wMiA9IGNhcHR1cmUub3V0cHV0KGNhdChwYXN0ZTAoImxpc3QoIiwgY29uZGl0aW9uLCAiPSciLCBsYW5ndWFnZSwgIi4iLCB2YXIxWzJdLCAiLiIsIHZhcjIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiJywgIiwgY29uZGl0aW9uLCAiPSciLCBsYW5ndWFnZSwgIi4iLCB2YXIxWzFdLCAiLiIsIHZhcjIsICInKSIpKSkKICAgIH0KICAgIHAxID0gcGxvdF9zbW9vdGgoeD1nZXQobW9kZWwpLCB2aWV3PXZhbHVlcywgY29uZD1ldmFsKHBhcnNlKHRleHQ9Y29uZF9wMSkpLCBybS5yYW5lZj1UUlVFKQogICAgcDIgPSBwbG90X3Ntb290aCh4PWdldChtb2RlbCksIHZpZXc9dmFsdWVzLCBjb25kPWV2YWwocGFyc2UodGV4dD1jb25kX3AyKSksIHJtLnJhbmVmPVRSVUUpCiAgICAjICMgb2xkIC0gaGFyZGNvZGVkCiAgICAjIHAxID0gcGxvdF9zbW9vdGgoeD1nZXQobW9kZWwpLCB2aWV3PXZhbHVlcywgY29uZD1saXN0KHRva2VuUG9vbGVkLm9yZD12YXIxLCB0b2tlblBvb2xlZC5vcmQ9dmFyMikpCiAgICAjIHAyID0gcGxvdF9zbW9vdGgoeD1nZXQobW9kZWwpLCB2aWV3PXZhbHVlcywgY29uZD1saXN0KHRva2VuUG9vbGVkLm9yZD12YXIyLCB0b2tlblBvb2xlZC5vcmQ9dmFyMSkpCiAgICAjIHNldCBSaG8gbWF4IHRvIHRoZSBtYXggb2YgdGhlIGZpdCArIGhhbGYgdGhlIGRpZmZlcmVuY2UgYmV0d2VlbiBtYXggb2YgdGhlIGZpdCBhbmQgdGhlIHVwcGVyIGxpbWl0CiAgICAjIG1heGltdW09bWF4KHAxJGZ2JGZpdCwgcDIkZnYkZml0KSsoKG1heChwMSRmdiR1bCwgcDIkZnYkdWwpLW1heChwMSRmdiRmaXQsIHAyJGZ2JGZpdCkpLzIpCiAgICBtYXhpbXVtPW1heChwMSRmdiR1bCwgcDIkZnYkdWwpCiAgICAKICAgICMgcGxvdCBpbiBwb2xhciBjb29yZGluYXRlcwogICAgcD1wbG90X2x5KHR5cGU9J3NjYXR0ZXJwb2xhcicsIG1vZGU9J2xpbmVzJykgJT4lIAogICAgICBhZGRfdHJhY2UodGhldGE9cDEkZnYkdGhldGFfdW5jdXRfeioxODAvcGksIHI9cDEkZnYkZml0LCBsaW5lPWxpc3QoY29sb3I9ImJsdWUiLCBkYXNoPSJkYXNoIiwgd2lkdGg9Mi41KSwgbmFtZT1uYW1lc19zbW9vdGhzWzFdKSAlPiUgCiAgICAgIGFkZF90cmFjZSh0aGV0YT1wMSRmdiR0aGV0YV91bmN1dF96KjE4MC9waSwgcj1wMSRmdiR1bCwgbGluZT1saXN0KGNvbG9yPSJibHVlIiwgZGFzaD0iZGFzaCIsIHdpZHRoPTAuNSksIHNob3dsZWdlbmQ9RkFMU0UpICU+JSAKICAgICAgYWRkX3RyYWNlKHRoZXRhPXAxJGZ2JHRoZXRhX3VuY3V0X3oqMTgwL3BpLCByPXAxJGZ2JGxsLCBsaW5lPWxpc3QoY29sb3I9ImJsdWUiLCBkYXNoPSJkYXNoIiwgIHdpZHRoPTAuNSksIHNob3dsZWdlbmQ9RkFMU0UpICU+JSAKICAgICAgYWRkX3RyYWNlKHRoZXRhPXAyJGZ2JHRoZXRhX3VuY3V0X3oqMTgwL3BpLCByPXAyJGZ2JGZpdCwgbGluZT1saXN0KGNvbG9yPSJyZWQiLCB3aWR0aD0yLjUpLCBuYW1lPW5hbWVzX3Ntb290aHNbMl0pICU+JSAKICAgICAgYWRkX3RyYWNlKHRoZXRhPXAyJGZ2JHRoZXRhX3VuY3V0X3oqMTgwL3BpLCByPXAyJGZ2JHVsLCBsaW5lPWxpc3QoY29sb3I9InJlZCIsIGRhc2g9ImRvdCIsIHdpZHRoPTAuNSksIHNob3dsZWdlbmQ9RkFMU0UpICU+JSAKICAgICAgYWRkX3RyYWNlKHRoZXRhPXAyJGZ2JHRoZXRhX3VuY3V0X3oqMTgwL3BpLCByPXAyJGZ2JGxsLCBsaW5lPWxpc3QoY29sb3I9InJlZCIsIGRhc2g9ImRvdCIsIHdpZHRoPTAuNSksIHNob3dsZWdlbmQ9RkFMU0UpICU+JQogICAgICBsYXlvdXQocG9sYXI9bGlzdChzZWN0b3I9YygyMCwxNjApLCByYWRpYWxheGlzPWxpc3QoYW5nbGU9OTAsIHJhbmdlPWMoMCxtYXhpbXVtKSksCiAgICAgICAgICAgICAgICAgICAgICAgIGFuZ3VsYXJheGlzPWxpc3QodGhldGF1bml0PSdyYWRpYW5zJywgZGlyZWN0aW9uPSJjbG9ja3dpc2UiLCByb3RhdGlvbj0wKSksIAogICAgICAgICAgICAgdGl0bGU9cGFzdGUwKCJHQU0gc21vb3RocyAiLCBsYW5ndWFnZSwgIiAiLCB2YXIxLCAiIHZzICIsIHZhcjIpLCAKICAgICAgICAgICAgIGxlZ2VuZD1saXN0KG9yaWVudGF0aW9uPSJoIiwgeGFuY2hvcj0iY2VudGVyIiwgeD0wLjUseT0wLjAxMikpCiAgICBTeXMuc2xlZXAoMCkKICAgIHByaW50KHApCiAgIyB0aGVyZSBhcmUgZGlmZmVyZW5jZXMuLi4KICB9ZWxzZXsKICAgICMgZ3JhYiBpbnRlcnZhbHMgb2Ygc2lnbmlmaWNhbnQgZGlmZmVyZW5jZXMgZnJvbSBvdXRwdXQKICAgIGlmIChsZW5ndGgobGFuZ3VhZ2UpPT0xICYmIGxlbmd0aCh2YXIxKT09MSAmJiBsZW5ndGgob3V0cHV0KT49OCl7CiAgICAjIGlmIChsZW5ndGgobGFuZ3VhZ2UpPT0xICYmIGxlbmd0aChvdXRwdXQpPj04KXsKICAgICAgc2lnX2RpZmYxID0gYyhhcy5kb3VibGUodW5saXN0KHN0cnNwbGl0KHVubGlzdChzdHJzcGxpdChvdXRwdXRbOF0sICIgIikpWzFdLCAiXHQiKSlbMl0pLCBhcy5kb3VibGUodW5saXN0KHN0cnNwbGl0KG91dHB1dFs4XSwgIiAiKSlbM10pKQogICAgfWVsc2UgaWYgKChsZW5ndGgobGFuZ3VhZ2UpPT0yICYmIGxlbmd0aChvdXRwdXQpPj03KSB8IChsZW5ndGgobGFuZ3VhZ2UpPT0xICYmIGxlbmd0aCh2YXIxKT09MiAmJiBsZW5ndGgob3V0cHV0KT49NykpewogICAgIyB9ZWxzZSBpZiAobGVuZ3RoKGxhbmd1YWdlKT09MiAmJiBsZW5ndGgob3V0cHV0KT49Nyl7CiAgICAgIHNpZ19kaWZmMSA9IGMoYXMuZG91YmxlKHVubGlzdChzdHJzcGxpdCh1bmxpc3Qoc3Ryc3BsaXQob3V0cHV0WzddLCAiICIpKVsxXSwgIlx0IikpWzJdKSwgYXMuZG91YmxlKHVubGlzdChzdHJzcGxpdChvdXRwdXRbN10sICIgIikpWzNdKSkKICAgIH0KICAgIGlmIChsZW5ndGgobGFuZ3VhZ2UpPT0xICYmIGxlbmd0aCh2YXIxKT09MSAmJiBsZW5ndGgob3V0cHV0KT49OSl7CiAgICAjIGlmIChsZW5ndGgobGFuZ3VhZ2UpPT0xICYmIGxlbmd0aChvdXRwdXQpPj05KXsKICAgICAgc2lnX2RpZmYyID0gYyhhcy5kb3VibGUodW5saXN0KHN0cnNwbGl0KHVubGlzdChzdHJzcGxpdChvdXRwdXRbOV0sICIgIikpWzFdLCAiXHQiKSlbMl0pLCBhcy5kb3VibGUodW5saXN0KHN0cnNwbGl0KG91dHB1dFs5XSwgIiAiKSlbM10pKQogICAgfWVsc2UgaWYgKChsZW5ndGgobGFuZ3VhZ2UpPT0yICYmIGxlbmd0aChvdXRwdXQpPj04KSB8IChsZW5ndGgobGFuZ3VhZ2UpPT0xICYmIGxlbmd0aCh2YXIxKT09MiAmJiBsZW5ndGgob3V0cHV0KT49OCkpewogICAgIyB9ZWxzZSBpZiAobGVuZ3RoKGxhbmd1YWdlKT09MiAmJiBsZW5ndGgob3V0cHV0KT49OCl7CiAgICAgIHNpZ19kaWZmMiA9IGMoYXMuZG91YmxlKHVubGlzdChzdHJzcGxpdCh1bmxpc3Qoc3Ryc3BsaXQob3V0cHV0WzhdLCAiICIpKVsxXSwgIlx0IikpWzJdKSwgYXMuZG91YmxlKHVubGlzdChzdHJzcGxpdChvdXRwdXRbOF0sICIgIikpWzNdKSkKICAgIH0KICAgIGlmIChsZW5ndGgobGFuZ3VhZ2UpPT0xICYmIGxlbmd0aCh2YXIxKT09MSAmJiBsZW5ndGgob3V0cHV0KT49MTApewogICAgIyBpZiAobGVuZ3RoKGxhbmd1YWdlKT09MSAmJiBsZW5ndGgob3V0cHV0KT49MTApewogICAgICBzaWdfZGlmZjMgPSBjKGFzLmRvdWJsZSh1bmxpc3Qoc3Ryc3BsaXQodW5saXN0KHN0cnNwbGl0KG91dHB1dFsxMF0sICIgIikpWzFdLCAiXHQiKSlbMl0pLCBhcy5kb3VibGUodW5saXN0KHN0cnNwbGl0KG91dHB1dFsxMF0sICIgIikpWzNdKSkKICAgIH1lbHNlIGlmICgobGVuZ3RoKGxhbmd1YWdlKT09MiAmJiBsZW5ndGgob3V0cHV0KT49OSkgfCAobGVuZ3RoKGxhbmd1YWdlKT09MSAmJiBsZW5ndGgodmFyMSk9PTIgJiYgbGVuZ3RoKG91dHB1dCk+PTkpKXsKICAgICMgfWVsc2UgaWYgKGxlbmd0aChsYW5ndWFnZSk9PTIgJiYgbGVuZ3RoKG91dHB1dCk+PTkpewogICAgICBzaWdfZGlmZjMgPSBjKGFzLmRvdWJsZSh1bmxpc3Qoc3Ryc3BsaXQodW5saXN0KHN0cnNwbGl0KG91dHB1dFs5XSwgIiAiKSlbMV0sICJcdCIpKVsyXSksIGFzLmRvdWJsZSh1bmxpc3Qoc3Ryc3BsaXQob3V0cHV0WzldLCAiICIpKVszXSkpCiAgICB9CiAgICBpZiAobGVuZ3RoKGxhbmd1YWdlKT09MSAmJiBsZW5ndGgodmFyMSk9PTEgJiYgbGVuZ3RoKG91dHB1dCk+PTExKXsKICAgICMgaWYgKGxlbmd0aChsYW5ndWFnZSk9PTEgJiYgbGVuZ3RoKG91dHB1dCk+PTExKXsKICAgICAgc2lnX2RpZmY0ID0gYyhhcy5kb3VibGUodW5saXN0KHN0cnNwbGl0KHVubGlzdChzdHJzcGxpdChvdXRwdXRbMTFdLCAiICIpKVsxXSwgIlx0IikpWzJdKSwgYXMuZG91YmxlKHVubGlzdChzdHJzcGxpdChvdXRwdXRbMTFdLCAiICIpKVszXSkpCiAgICB9ZWxzZSBpZiAoKGxlbmd0aChsYW5ndWFnZSk9PTIgJiYgbGVuZ3RoKG91dHB1dCk+PTEwKSB8IChsZW5ndGgobGFuZ3VhZ2UpPT0xICYmIGxlbmd0aCh2YXIxKT09MiAmJiBsZW5ndGgob3V0cHV0KT49MTApKXsKICAgICMgfWVsc2UgaWYgKGxlbmd0aChsYW5ndWFnZSk9PTIgJiYgbGVuZ3RoKG91dHB1dCk+PTEwKXsKICAgICAgc2lnX2RpZmY0ID0gYyhhcy5kb3VibGUodW5saXN0KHN0cnNwbGl0KHVubGlzdChzdHJzcGxpdChvdXRwdXRbMTBdLCAiICIpKVsxXSwgIlx0IikpWzJdKSwgYXMuZG91YmxlKHVubGlzdChzdHJzcGxpdChvdXRwdXRbMTBdLCAiICIpKVszXSkpCiAgICB9CgogICAgCiAgICAjIHdyaXRlIGludGVydmFscyBvZiBzaWduaWZpY2FudCBkaWZmZXJlbmNlIHRvIHZhcmlhYmxlCiAgICBpZiAoKGxlbmd0aChsYW5ndWFnZSk9PTEgJiYgbGVuZ3RoKHZhcjEpPT0xICYmIGxlbmd0aChvdXRwdXQpPj0xMSkgfCAoKGxlbmd0aChsYW5ndWFnZSk9PTIgJiYgbGVuZ3RoKG91dHB1dCk+PTEwKSkgfCAKICAgICAgICAobGVuZ3RoKGxhbmd1YWdlKT09MSAmJiBsZW5ndGgodmFyMSk9PTIgJiYgbGVuZ3RoKG91dHB1dCk+PTEwKSl7CiAgICAjIGlmICgobGVuZ3RoKGxhbmd1YWdlKT09MSAmJiBsZW5ndGgob3V0cHV0KT49MTEpIHwgKGxlbmd0aChsYW5ndWFnZSk9PTIgJiYgbGVuZ3RoKG91dHB1dCk+PTEwKSl7CiAgICAgIGRhdDEgPSBjKHNpZ19kaWZmMSwgc2lnX2RpZmYyLCBzaWdfZGlmZjMsIHNpZ19kaWZmNCkKICAgIH1lbHNlIGlmICgobGVuZ3RoKGxhbmd1YWdlKT09MSAmJiBsZW5ndGgodmFyMSk9PTEgJiYgbGVuZ3RoKG91dHB1dCk+PTEwKSB8ICgobGVuZ3RoKGxhbmd1YWdlKT09MiAmJiBsZW5ndGgob3V0cHV0KT49OSkpIHwgCiAgICAgICAgICAgICAgKGxlbmd0aChsYW5ndWFnZSk9PTEgJiYgbGVuZ3RoKHZhcjEpPT0yICYmIGxlbmd0aChvdXRwdXQpPj05KSl7CiAgICAjIH1lbHNlIGlmICgobGVuZ3RoKGxhbmd1YWdlKT09MSAmJiBsZW5ndGgob3V0cHV0KT49MTApIHwgKGxlbmd0aChsYW5ndWFnZSk9PTIgJiYgbGVuZ3RoKG91dHB1dCk+PTkpKXsKICAgICAgZGF0MSA9IGMoc2lnX2RpZmYxLCBzaWdfZGlmZjIsIHNpZ19kaWZmMykKICAgIH1lbHNlIGlmICgobGVuZ3RoKGxhbmd1YWdlKT09MSAmJiBsZW5ndGgodmFyMSk9PTEgJiYgbGVuZ3RoKG91dHB1dCk+PTkpIHwgKChsZW5ndGgobGFuZ3VhZ2UpPT0yICYmIGxlbmd0aChvdXRwdXQpPj04KSkgfCAKICAgICAgICAgICAgICAobGVuZ3RoKGxhbmd1YWdlKT09MSAmJiBsZW5ndGgodmFyMSk9PTIgJiYgbGVuZ3RoKG91dHB1dCk+PTgpKXsKICAgICMgfWVsc2UgaWYgKChsZW5ndGgobGFuZ3VhZ2UpPT0xICYmIGxlbmd0aChvdXRwdXQpPj05KSB8IChsZW5ndGgobGFuZ3VhZ2UpPT0yICYmIGxlbmd0aChvdXRwdXQpPj04KSl7CiAgICAgIGRhdDEgPSBjKHNpZ19kaWZmMSwgc2lnX2RpZmYyKQogICAgfWVsc2V7CiAgICAgIGRhdDEgPSBzaWdfZGlmZjEKICAgIH0KICAgICMgb2xkCiAgICAjIGFzc2lnbihwYXN0ZTAoImludF9zaWdfZGlmZl8iLCB2YXIxLCAiXyIsIHZhcjIpLCBkYXQxLCBlbnZpciA9IC5HbG9iYWxFbnYpCiAgICBpZiAobGVuZ3RoKHZhcjEpPT0xKXsKICAgICAgYXNzaWduKHBhc3RlMCgiaW50X3NpZ19kaWZmXyIsIHZhcjEsICJfIiwgdmFyMiksIGRhdDEsIGVudmlyID0gLkdsb2JhbEVudikKICAgIH1lbHNlewogICAgICBhc3NpZ24ocGFzdGUwKCJpbnRfc2lnX2RpZmZfIiwgdmFyMVsxXSwgIl8iLCB2YXIxWzJdLCAiXyIsIHZhcjIsICJfIiwgbGFuZ3VhZ2UpLCBkYXQxLCBlbnZpciA9IC5HbG9iYWxFbnYpCiAgICB9CiAgICBybShkYXQxLCBvdXRwdXQpCiAgICAjIHJ1biBwbG90X3Ntb290aCB0byBncmFiIGRhdGEgZm9yIHBvbGFyIHBsb3RzCiAgICBpZiAoY29uZGl0aW9uPT0idG9rZW5Qb29sZWQub3JkIiAmJiBsZW5ndGgobGFuZ3VhZ2UpPT0xKXsKICAgICAgY29uZF9wMSA9IGNhcHR1cmUub3V0cHV0KGNhdChwYXN0ZTAoImxpc3QoIiwgY29uZGl0aW9uLCAiPXZhcjEpIikpKQogICAgICBjb25kX3AyID0gY2FwdHVyZS5vdXRwdXQoY2F0KHBhc3RlMCgibGlzdCgiLCBjb25kaXRpb24sICI9dmFyMikiKSkpCiAgICB9ZWxzZSBpZiAoY29uZGl0aW9uPT0ibGFuZ05vdGVJbnQub3JkIiAmJiBsZW5ndGgobGFuZ3VhZ2UpPT0yKXsKICAgICAgY29uZF9wMSA9IGNhcHR1cmUub3V0cHV0KGNhdChwYXN0ZTAoImxpc3QoIiwgY29uZGl0aW9uLCAiPSciLCBsYW5ndWFnZVsxXSwgIi4iLCB2YXIxLCAiLiIsIHZhcjIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICInLCAiLCBjb25kaXRpb24sICI9JyIsIGxhbmd1YWdlWzJdLCAiLiIsIHZhcjEsICIuIiwgdmFyMiwgIicpIikpKQogICAgICBjb25kX3AyID0gY2FwdHVyZS5vdXRwdXQoY2F0KHBhc3RlMCgibGlzdCgiLCBjb25kaXRpb24sICI9JyIsIGxhbmd1YWdlWzJdLCAiLiIsIHZhcjEsICIuIiwgdmFyMiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICInLCAiLCBjb25kaXRpb24sICI9JyIsIGxhbmd1YWdlWzFdLCAiLiIsIHZhcjEsICIuIiwgdmFyMiwgIicpIikpKQogICAgfWVsc2UgaWYgKGNvbmRpdGlvbj09ImxhbmdOb3RlSW50Lm9yZCIgJiYgbGVuZ3RoKGxhbmd1YWdlKT09MSAmJiBsZW5ndGgodmFyMSk9PTIpewogICAgICBjb25kX3AxID0gY2FwdHVyZS5vdXRwdXQoY2F0KHBhc3RlMCgibGlzdCgiLCBjb25kaXRpb24sICI9JyIsIGxhbmd1YWdlLCAiLiIsIHZhcjFbMV0sICIuIiwgdmFyMiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICInLCAiLCBjb25kaXRpb24sICI9JyIsIGxhbmd1YWdlLCAiLiIsIHZhcjFbMl0sICIuIiwgdmFyMiwgIicpIikpKQogICAgICBjb25kX3AyID0gY2FwdHVyZS5vdXRwdXQoY2F0KHBhc3RlMCgibGlzdCgiLCBjb25kaXRpb24sICI9JyIsIGxhbmd1YWdlLCAiLiIsIHZhcjFbMl0sICIuIiwgdmFyMiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICInLCAiLCBjb25kaXRpb24sICI9JyIsIGxhbmd1YWdlLCAiLiIsIHZhcjFbMV0sICIuIiwgdmFyMiwgIicpIikpKQogICAgfQogICAgcDEgPSBwbG90X3Ntb290aCh4PWdldChtb2RlbCksIHZpZXc9dmFsdWVzLCBjb25kPWV2YWwocGFyc2UodGV4dD1jb25kX3AxKSksIHJtLnJhbmVmPVRSVUUpCiAgICBwMiA9IHBsb3Rfc21vb3RoKHg9Z2V0KG1vZGVsKSwgdmlldz12YWx1ZXMsIGNvbmQ9ZXZhbChwYXJzZSh0ZXh0PWNvbmRfcDIpKSwgcm0ucmFuZWY9VFJVRSkKICAgICMgc2V0IFJobyBtYXggdG8gdGhlIG1heCBvZiB0aGUgZml0ICsgaGFsZiB0aGUgZGlmZmVyZW5jZSBiZXR3ZWVuIG1heCBvZiB0aGUgZml0IGFuZCB0aGUgdXBwZXIgbGltaXQKICAgICMgbWF4aW11bT1tYXgocDEkZnYkZml0LCBwMiRmdiRmaXQpKygobWF4KHAxJGZ2JHVsLCBwMiRmdiR1bCktbWF4KHAxJGZ2JGZpdCwgcDIkZnYkZml0KSkvMikKICAgIG1heGltdW09bWF4KHAxJGZ2JHVsLCBwMiRmdiR1bCkKICAgIAogICAgIyBwbG90IGluIHBvbGFyIGNvb3JkaW5hdGVzCiAgICBpZiAoZXhpc3RzKCJzaWdfZGlmZjQiKSl7CiAgICAgIHA9cGxvdF9seSh0eXBlPSdzY2F0dGVycG9sYXInLCBtb2RlPSdsaW5lcycpICU+JSAKICAgICAgICBhZGRfdHJhY2UodGhldGE9cDEkZnYkdGhldGFfdW5jdXRfeioxODAvcGksIHI9cDEkZnYkZml0LCBsaW5lPWxpc3QoY29sb3I9ImJsdWUiLCBkYXNoPSJkYXNoIiwgd2lkdGg9Mi41KSwgbmFtZT1uYW1lc19zbW9vdGhzWzFdKSAlPiUgCiAgICAgICAgYWRkX3RyYWNlKHRoZXRhPXAxJGZ2JHRoZXRhX3VuY3V0X3oqMTgwL3BpLCByPXAxJGZ2JHVsLCBsaW5lPWxpc3QoY29sb3I9ImJsdWUiLCBkYXNoPSJkYXNoIiwgd2lkdGg9MC41KSwgc2hvd2xlZ2VuZD1GQUxTRSkgJT4lIAogICAgICAgIGFkZF90cmFjZSh0aGV0YT1wMSRmdiR0aGV0YV91bmN1dF96KjE4MC9waSwgcj1wMSRmdiRsbCwgbGluZT1saXN0KGNvbG9yPSJibHVlIiwgZGFzaD0iZGFzaCIsIHdpZHRoPTAuNSksIHNob3dsZWdlbmQ9RkFMU0UpICU+JSAKICAgICAgICBhZGRfdHJhY2UodGhldGE9cDIkZnYkdGhldGFfdW5jdXRfeioxODAvcGksIHI9cDIkZnYkZml0LCBsaW5lPWxpc3QoY29sb3I9InJlZCIsIHdpZHRoPTIuNSksIG5hbWU9bmFtZXNfc21vb3Roc1syXSkgJT4lIAogICAgICAgIGFkZF90cmFjZSh0aGV0YT1wMiRmdiR0aGV0YV91bmN1dF96KjE4MC9waSwgcj1wMiRmdiR1bCwgbGluZT1saXN0KGNvbG9yPSJyZWQiLCBkYXNoPSJkb3QiLCB3aWR0aD0wLjUpLCBzaG93bGVnZW5kPUZBTFNFKSAlPiUgCiAgICAgICAgYWRkX3RyYWNlKHRoZXRhPXAyJGZ2JHRoZXRhX3VuY3V0X3oqMTgwL3BpLCByPXAyJGZ2JGxsLCBsaW5lPWxpc3QoY29sb3I9InJlZCIsIGRhc2g9ImRvdCIsIHdpZHRoPTAuNSksIHNob3dsZWdlbmQ9RkFMU0UpICU+JQogICAgICAgIGFkZF90cmFjZSh0aGV0YT1zZXEoc2lnX2RpZmYxWzFdKjE4MC9waSwgc2lnX2RpZmYxWzJdKjE4MC9waSwgbGVuZ3RoLm91dD0yMCksIAogICAgICAgICAgICAgICAgICByPWMoMCwgcmVwKG1heGltdW0sIDE4KSwgMCksIGxpbmU9bGlzdChjb2xvcj0iYmxhY2siLCB3aWR0aD0wLjUpLCBmaWxsPSJ0b3NlbGYiLCBmaWxsY29sb3I9cmdiKDAsMCwwLG1heD0yNTUsYWxwaGE9MjUpLCBzaG93bGVnZW5kPUZBTFNFKSAlPiUKICAgICAgICBhZGRfdHJhY2UodGhldGE9c2VxKHNpZ19kaWZmMlsxXSoxODAvcGksIHNpZ19kaWZmMlsyXSoxODAvcGksIGxlbmd0aC5vdXQ9MjApLCAKICAgICAgICAgICAgICAgICAgcj1jKDAsIHJlcChtYXhpbXVtLCAxOCksIDApLCBsaW5lPWxpc3QoY29sb3I9ImJsYWNrIiwgd2lkdGg9MC41KSwgZmlsbD0idG9zZWxmIiwgZmlsbGNvbG9yPXJnYigwLDAsMCxtYXg9MjU1LGFscGhhPTI1KSwgc2hvd2xlZ2VuZD1GQUxTRSkgJT4lCiAgICAgICAgYWRkX3RyYWNlKHRoZXRhPXNlcShzaWdfZGlmZjNbMV0qMTgwL3BpLCBzaWdfZGlmZjNbMl0qMTgwL3BpLCBsZW5ndGgub3V0PTIwKSwgCiAgICAgICAgICAgICAgICAgIHI9YygwLCByZXAobWF4aW11bSwgMTgpLCAwKSwgbGluZT1saXN0KGNvbG9yPSJibGFjayIsIHdpZHRoPTAuNSksIGZpbGw9InRvc2VsZiIsIGZpbGxjb2xvcj1yZ2IoMCwwLDAsbWF4PTI1NSxhbHBoYT0yNSksIHNob3dsZWdlbmQ9RkFMU0UpICU+JQogICAgICAgIGFkZF90cmFjZSh0aGV0YT1zZXEoc2lnX2RpZmY0WzFdKjE4MC9waSwgc2lnX2RpZmY0WzJdKjE4MC9waSwgbGVuZ3RoLm91dD0yMCksIAogICAgICAgICAgICAgICAgICByPWMoMCwgcmVwKG1heGltdW0sIDE4KSwgMCksIGxpbmU9bGlzdChjb2xvcj0iYmxhY2siLCB3aWR0aD0wLjUpLCBmaWxsPSJ0b3NlbGYiLCBmaWxsY29sb3I9cmdiKDAsMCwwLG1heD0yNTUsYWxwaGE9MjUpLCBzaG93bGVnZW5kPUZBTFNFKSAlPiUKICAgICAgICBsYXlvdXQocG9sYXI9bGlzdChzZWN0b3I9YygyMCwxNjApLCByYWRpYWxheGlzPWxpc3QoYW5nbGU9OTAsIHJhbmdlPWMoMCxtYXhpbXVtKSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgYW5ndWxhcmF4aXM9bGlzdCh0aGV0YXVuaXQ9J3JhZGlhbnMnLCBkaXJlY3Rpb249ImNsb2Nrd2lzZSIsIHJvdGF0aW9uPTApKSwgCiAgICAgICAgICAgICAgIHRpdGxlPXBsb3RfdGl0bGUsIGxlZ2VuZD1saXN0KG9yaWVudGF0aW9uPSJoIiwgeGFuY2hvcj0iY2VudGVyIiwgeD0wLjUsIHk9MC4wMTIpKQogICAgICBTeXMuc2xlZXAoMCkKICAgICAgcHJpbnQocCkKICAgIH1lbHNlIGlmIChleGlzdHMoInNpZ19kaWZmMyIpKXsKICAgICAgcD1wbG90X2x5KHR5cGU9J3NjYXR0ZXJwb2xhcicsIG1vZGU9J2xpbmVzJykgJT4lIAogICAgICAgIGFkZF90cmFjZSh0aGV0YT1wMSRmdiR0aGV0YV91bmN1dF96KjE4MC9waSwgcj1wMSRmdiRmaXQsIGxpbmU9bGlzdChjb2xvcj0iYmx1ZSIsIGRhc2g9ImRhc2giLCB3aWR0aD0yLjUpLCBuYW1lPW5hbWVzX3Ntb290aHNbMV0pICU+JSAKICAgICAgICBhZGRfdHJhY2UodGhldGE9cDEkZnYkdGhldGFfdW5jdXRfeioxODAvcGksIHI9cDEkZnYkdWwsIGxpbmU9bGlzdChjb2xvcj0iYmx1ZSIsIGRhc2g9ImRhc2giLCB3aWR0aD0wLjUpLCBzaG93bGVnZW5kPUZBTFNFKSAlPiUgCiAgICAgICAgYWRkX3RyYWNlKHRoZXRhPXAxJGZ2JHRoZXRhX3VuY3V0X3oqMTgwL3BpLCByPXAxJGZ2JGxsLCBsaW5lPWxpc3QoY29sb3I9ImJsdWUiLCBkYXNoPSJkYXNoIiwgd2lkdGg9MC41KSwgc2hvd2xlZ2VuZD1GQUxTRSkgJT4lIAogICAgICAgIGFkZF90cmFjZSh0aGV0YT1wMiRmdiR0aGV0YV91bmN1dF96KjE4MC9waSwgcj1wMiRmdiRmaXQsIGxpbmU9bGlzdChjb2xvcj0icmVkIiwgd2lkdGg9Mi41KSwgbmFtZT1uYW1lc19zbW9vdGhzWzJdKSAlPiUgCiAgICAgICAgYWRkX3RyYWNlKHRoZXRhPXAyJGZ2JHRoZXRhX3VuY3V0X3oqMTgwL3BpLCByPXAyJGZ2JHVsLCBsaW5lPWxpc3QoY29sb3I9InJlZCIsIGRhc2g9ImRvdCIsIHdpZHRoPTAuNSksIHNob3dsZWdlbmQ9RkFMU0UpICU+JSAKICAgICAgICBhZGRfdHJhY2UodGhldGE9cDIkZnYkdGhldGFfdW5jdXRfeioxODAvcGksIHI9cDIkZnYkbGwsIGxpbmU9bGlzdChjb2xvcj0icmVkIiwgZGFzaD0iZG90Iiwgd2lkdGg9MC41KSwgc2hvd2xlZ2VuZD1GQUxTRSkgJT4lCiAgICAgICAgYWRkX3RyYWNlKHRoZXRhPXNlcShzaWdfZGlmZjFbMV0qMTgwL3BpLCBzaWdfZGlmZjFbMl0qMTgwL3BpLCBsZW5ndGgub3V0PTIwKSwgCiAgICAgICAgICAgICAgICAgIHI9YygwLCByZXAobWF4aW11bSwgMTgpLCAwKSwgbGluZT1saXN0KGNvbG9yPSJibGFjayIsIHdpZHRoPTAuNSksIGZpbGw9InRvc2VsZiIsIGZpbGxjb2xvcj1yZ2IoMCwwLDAsbWF4PTI1NSxhbHBoYT0yNSksIHNob3dsZWdlbmQ9RkFMU0UpICU+JQogICAgICAgIGFkZF90cmFjZSh0aGV0YT1zZXEoc2lnX2RpZmYyWzFdKjE4MC9waSwgc2lnX2RpZmYyWzJdKjE4MC9waSwgbGVuZ3RoLm91dD0yMCksIAogICAgICAgICAgICAgICAgICByPWMoMCwgcmVwKG1heGltdW0sIDE4KSwgMCksIGxpbmU9bGlzdChjb2xvcj0iYmxhY2siLCB3aWR0aD0wLjUpLCBmaWxsPSJ0b3NlbGYiLCBmaWxsY29sb3I9cmdiKDAsMCwwLG1heD0yNTUsYWxwaGE9MjUpLCBzaG93bGVnZW5kPUZBTFNFKSAlPiUKICAgICAgICBhZGRfdHJhY2UodGhldGE9c2VxKHNpZ19kaWZmM1sxXSoxODAvcGksIHNpZ19kaWZmM1syXSoxODAvcGksIGxlbmd0aC5vdXQ9MjApLCAKICAgICAgICAgICAgICAgICAgcj1jKDAsIHJlcChtYXhpbXVtLCAxOCksIDApLCBsaW5lPWxpc3QoY29sb3I9ImJsYWNrIiwgd2lkdGg9MC41KSwgZmlsbD0idG9zZWxmIiwgZmlsbGNvbG9yPXJnYigwLDAsMCxtYXg9MjU1LGFscGhhPTI1KSwgc2hvd2xlZ2VuZD1GQUxTRSkgJT4lCiAgICAgICAgbGF5b3V0KHBvbGFyPWxpc3Qoc2VjdG9yPWMoMjAsMTYwKSwgcmFkaWFsYXhpcz1saXN0KGFuZ2xlPTkwLCByYW5nZT1jKDAsbWF4aW11bSkpLAogICAgICAgICAgICAgICAgICAgICAgICAgIGFuZ3VsYXJheGlzPWxpc3QodGhldGF1bml0PSdyYWRpYW5zJywgZGlyZWN0aW9uPSJjbG9ja3dpc2UiLCByb3RhdGlvbj0wKSksIAogICAgICAgICAgICAgICB0aXRsZT1wbG90X3RpdGxlLCBsZWdlbmQ9bGlzdChvcmllbnRhdGlvbj0iaCIsIHhhbmNob3I9ImNlbnRlciIsIHg9MC41LHk9MC4wMTIpKQogICAgICBTeXMuc2xlZXAoMCkKICAgICAgcHJpbnQocCkKICAgIH1lbHNlIGlmIChleGlzdHMoInNpZ19kaWZmMiIpKXsKICAgICAgcD1wbG90X2x5KHR5cGU9J3NjYXR0ZXJwb2xhcicsIG1vZGU9J2xpbmVzJykgJT4lIAogICAgICAgIGFkZF90cmFjZSh0aGV0YT1wMSRmdiR0aGV0YV91bmN1dF96KjE4MC9waSwgcj1wMSRmdiRmaXQsIGxpbmU9bGlzdChjb2xvcj0iYmx1ZSIsIGRhc2g9ImRhc2giLCB3aWR0aD0yLjUpLCBuYW1lPW5hbWVzX3Ntb290aHNbMV0pICU+JSAKICAgICAgICBhZGRfdHJhY2UodGhldGE9cDEkZnYkdGhldGFfdW5jdXRfeioxODAvcGksIHI9cDEkZnYkdWwsIGxpbmU9bGlzdChjb2xvcj0iYmx1ZSIsIGRhc2g9ImRhc2giLCB3aWR0aD0wLjUpLCBzaG93bGVnZW5kPUZBTFNFKSAlPiUgCiAgICAgICAgYWRkX3RyYWNlKHRoZXRhPXAxJGZ2JHRoZXRhX3VuY3V0X3oqMTgwL3BpLCByPXAxJGZ2JGxsLCBsaW5lPWxpc3QoY29sb3I9ImJsdWUiLCBkYXNoPSJkYXNoIiwgd2lkdGg9MC41KSwgc2hvd2xlZ2VuZD1GQUxTRSkgJT4lIAogICAgICAgIGFkZF90cmFjZSh0aGV0YT1wMiRmdiR0aGV0YV91bmN1dF96KjE4MC9waSwgcj1wMiRmdiRmaXQsIGxpbmU9bGlzdChjb2xvcj0icmVkIiwgd2lkdGg9Mi41KSwgbmFtZT1uYW1lc19zbW9vdGhzWzJdKSAlPiUgCiAgICAgICAgYWRkX3RyYWNlKHRoZXRhPXAyJGZ2JHRoZXRhX3VuY3V0X3oqMTgwL3BpLCByPXAyJGZ2JHVsLCBsaW5lPWxpc3QoY29sb3I9InJlZCIsIGRhc2g9ImRvdCIsIHdpZHRoPTAuNSksIHNob3dsZWdlbmQ9RkFMU0UpICU+JSAKICAgICAgICBhZGRfdHJhY2UodGhldGE9cDIkZnYkdGhldGFfdW5jdXRfeioxODAvcGksIHI9cDIkZnYkbGwsIGxpbmU9bGlzdChjb2xvcj0icmVkIiwgZGFzaD0iZG90Iiwgd2lkdGg9MC41KSwgc2hvd2xlZ2VuZD1GQUxTRSkgJT4lCiAgICAgICAgYWRkX3RyYWNlKHRoZXRhPXNlcShzaWdfZGlmZjFbMV0qMTgwL3BpLCBzaWdfZGlmZjFbMl0qMTgwL3BpLCBsZW5ndGgub3V0PTIwKSwgCiAgICAgICAgICAgICAgICAgIHI9YygwLCByZXAobWF4aW11bSwgMTgpLCAwKSwgbGluZT1saXN0KGNvbG9yPSJibGFjayIsIHdpZHRoPTAuNSksIGZpbGw9InRvc2VsZiIsIGZpbGxjb2xvcj1yZ2IoMCwwLDAsbWF4PTI1NSxhbHBoYT0yNSksIHNob3dsZWdlbmQ9RkFMU0UpICU+JQogICAgICAgIGFkZF90cmFjZSh0aGV0YT1zZXEoc2lnX2RpZmYyWzFdKjE4MC9waSwgc2lnX2RpZmYyWzJdKjE4MC9waSwgbGVuZ3RoLm91dD0yMCksIAogICAgICAgICAgICAgICAgICByPWMoMCwgcmVwKG1heGltdW0sIDE4KSwgMCksIGxpbmU9bGlzdChjb2xvcj0iYmxhY2siLCB3aWR0aD0wLjUpLCBmaWxsPSJ0b3NlbGYiLCBmaWxsY29sb3I9cmdiKDAsMCwwLG1heD0yNTUsYWxwaGE9MjUpLCBzaG93bGVnZW5kPUZBTFNFKSAlPiUKICAgICAgICBsYXlvdXQocG9sYXI9bGlzdChzZWN0b3I9YygyMCwxNjApLCByYWRpYWxheGlzPWxpc3QoYW5nbGU9OTAsIHJhbmdlPWMoMCxtYXhpbXVtKSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgYW5ndWxhcmF4aXM9bGlzdCh0aGV0YXVuaXQ9J3JhZGlhbnMnLCBkaXJlY3Rpb249ImNsb2Nrd2lzZSIsIHJvdGF0aW9uPTApKSwgCiAgICAgICAgICAgICAgIHRpdGxlPXBsb3RfdGl0bGUsIGxlZ2VuZD1saXN0KG9yaWVudGF0aW9uPSJoIiwgeGFuY2hvcj0iY2VudGVyIiwgeD0wLjUseT0wLjAxMikpCiAgICAgIFN5cy5zbGVlcCgwKQogICAgICBwcmludChwKQogICAgfWVsc2V7CiAgICAgIHA9cGxvdF9seSh0eXBlPSdzY2F0dGVycG9sYXInLCBtb2RlPSdsaW5lcycpICU+JSAKICAgICAgICBhZGRfdHJhY2UodGhldGE9cDEkZnYkdGhldGFfdW5jdXRfeioxODAvcGksIHI9cDEkZnYkZml0LCBsaW5lPWxpc3QoY29sb3I9ImJsdWUiLCBkYXNoPSJkYXNoIiwgd2lkdGg9Mi41KSwgbmFtZT1uYW1lc19zbW9vdGhzWzFdKSAlPiUgCiAgICAgICAgYWRkX3RyYWNlKHRoZXRhPXAxJGZ2JHRoZXRhX3VuY3V0X3oqMTgwL3BpLCByPXAxJGZ2JHVsLCBsaW5lPWxpc3QoY29sb3I9ImJsdWUiLCBkYXNoPSJkYXNoIiwgd2lkdGg9MC41KSwgc2hvd2xlZ2VuZD1GQUxTRSkgJT4lIAogICAgICAgIGFkZF90cmFjZSh0aGV0YT1wMSRmdiR0aGV0YV91bmN1dF96KjE4MC9waSwgcj1wMSRmdiRsbCwgbGluZT1saXN0KGNvbG9yPSJibHVlIiwgZGFzaD0iZGFzaCIsIHdpZHRoPTAuNSksIHNob3dsZWdlbmQ9RkFMU0UpICU+JSAKICAgICAgICBhZGRfdHJhY2UodGhldGE9cDIkZnYkdGhldGFfdW5jdXRfeioxODAvcGksIHI9cDIkZnYkZml0LCBsaW5lPWxpc3QoY29sb3I9InJlZCIsIHdpZHRoPTIuNSksIG5hbWU9bmFtZXNfc21vb3Roc1syXSkgJT4lIAogICAgICAgIGFkZF90cmFjZSh0aGV0YT1wMiRmdiR0aGV0YV91bmN1dF96KjE4MC9waSwgcj1wMiRmdiR1bCwgbGluZT1saXN0KGNvbG9yPSJyZWQiLCBkYXNoPSJkb3QiLCB3aWR0aD0wLjUpLCBzaG93bGVnZW5kPUZBTFNFKSAlPiUgCiAgICAgICAgYWRkX3RyYWNlKHRoZXRhPXAyJGZ2JHRoZXRhX3VuY3V0X3oqMTgwL3BpLCByPXAyJGZ2JGxsLCBsaW5lPWxpc3QoY29sb3I9InJlZCIsIGRhc2g9ImRvdCIsIHdpZHRoPTAuNSksIHNob3dsZWdlbmQ9RkFMU0UpICU+JQogICAgICAgIGFkZF90cmFjZSh0aGV0YT1zZXEoc2lnX2RpZmYxWzFdKjE4MC9waSwgc2lnX2RpZmYxWzJdKjE4MC9waSwgbGVuZ3RoLm91dD0yMCksIAogICAgICAgICAgICAgICAgICByPWMoMCwgcmVwKG1heGltdW0sIDE4KSwgMCksIGxpbmU9bGlzdChjb2xvcj0iYmxhY2siLCB3aWR0aD0wLjUpLCBmaWxsPSJ0b3NlbGYiLCBmaWxsY29sb3I9cmdiKDAsMCwwLG1heD0yNTUsYWxwaGE9MjUpLCBzaG93bGVnZW5kPUZBTFNFKSAlPiUKICAgICAgICBsYXlvdXQocG9sYXI9bGlzdChzZWN0b3I9YygyMCwxNjApLCByYWRpYWxheGlzPWxpc3QoYW5nbGU9OTAsIHJhbmdlPWMoMCxtYXhpbXVtKSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgYW5ndWxhcmF4aXM9bGlzdCh0aGV0YXVuaXQ9J3JhZGlhbnMnLCBkaXJlY3Rpb249ImNsb2Nrd2lzZSIsIHJvdGF0aW9uPTApKSwgCiAgICAgICAgICAgICAgIHRpdGxlPXBsb3RfdGl0bGUsIGxlZ2VuZD1saXN0KG9yaWVudGF0aW9uPSJoIiwgeGFuY2hvcj0iY2VudGVyIiwgeD0wLjUseT0wLjAxMikpCiAgICAgIFN5cy5zbGVlcCgwKQogICAgICBwcmludChwKQogICAgfQogIH0KICAjIG9yY2Egc2hvdWxkIHdvcmsgd2l0aCBwbG90bHkgNC45LjAgYWZ0ZXIgbG9hZGluZyB0aGUgb3JjYSBtb2R1bGUgYmVmb3JlIHN0YXRpbmcgUiBhbmQgUlN0dWRpbwogIGlmKHNhdmU9PVRSVUUpCiAgewogICAgb3JjYShwLCBwYXN0ZShmaWxlTmFtZSwiLnBkZiIsc2VwPSIiKSxmb3JtYXQ9InBkZiIpCiAgICBvcmNhKHAsIHBhc3RlKGZpbGVOYW1lLCIucGRmIixzZXA9IiIpLGZvcm1hdD0ianBlZyIpCiAgfQp9CmBgYAoKCiMgTG9hZCBmaW5hbCBtb2RlbHMKCmBgYHtyIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIGVycm9yPUZBTFNFfQojIGxvYWQgZmluYWwgbW9kZWwgZm9yIEgxCk5vdGVzLmdhbS5BUi5Nb2QyID0gcmVhZFJEUygidXBkYXRlZF9tb2RlbHMvTm90ZXMuZ2FtLkFSLk1vZDIucmRzIikKCiMgbG9hZCBmaW5hbCBtb2RlbCBmb3IgSDFiClZBUi5nYW0uQVIuTW9kMiA9IHJlYWRSRFMoInVwZGF0ZWRfbW9kZWxzL1ZBUi5nYW0uQVIuTW9kMi5yZHMiKQoKIyBsb2FkIGZpbmFsIG1vZGVscyBmb3IgSDIKTlpFLmdhbS5BUi5Nb2QyID0gcmVhZFJEUygidXBkYXRlZF9tb2RlbHMvTlpFLmdhbS5BUi5Nb2QyLnJkcyIpClRvbmdhbi5nYW0uQVIuTW9kMiA9IHJlYWRSRFMoInVwZGF0ZWRfbW9kZWxzL1Rvbmdhbi5nYW0uQVIuTW9kMi5yZHMiKQpgYGAKCiMgQ3JlYXRlIHBhcGVyIHBsb3RzCgojIyAobmV3KSBGaWd1cmUgNCBIMSAtPiBwcmVkaWN0IGF2ZXJhZ2UgdmFsdWVzIGZvciBub3RlIHByb2R1Y3Rpb25zIE5aRSB2cyBUb25nYW4KCmBgYHtyIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIGVycm9yPUZBTFNFfQojIGNyZWF0ZSBkZk5vdGVzCmRmIDwtIHJlYWQuY3N2KCJhbGxfZGF0YV9OWkVfVG9uZ2FuX3dfY29udGV4dF9jaGVja2VkXzdfTWFyY2hfMjAxOV9ub3RfY3V0X2NoZWNrZWRfMjdfQXByLmNzdiIsIHNlcD0nLCcsIHN0cmluZ3NBc0ZhY3RvcnMgPSBGKQpkZiRYID0gTlVMTApkZiR0b2tlblBvb2xlZCA8LSBmYWN0b3IoZGYkdG9rZW5Qb29sZWQpCmRmJHN1YmplY3QgPC0gZmFjdG9yKGRmJHN1YmplY3QpCmRmJHNleCA8LSBmYWN0b3IoZGYkc2V4KQpkZiRuYXRpdmVfbGcgPC0gZmFjdG9yKGRmJG5hdGl2ZV9sZykKZGYkcGxheWluZ19wcm9maWNpZW5jeVtkZiRwbGF5aW5nX3Byb2ZpY2llbmN5ID09ICJpbnRlcm1lZGlhdGUiXSA8LSAiYW1hdGV1ciIKZGYkcGxheWluZ19wcm9maWNpZW5jeSA8LSBmYWN0b3IoZGYkcGxheWluZ19wcm9maWNpZW5jeSwgbGV2ZWxzID0gYygiYW1hdGV1ciIsInNlbWktcHJvZmVzc2lvbmFsIiwicHJvZmVzc2lvbmFsIikpCmRmJGJsb2NrIDwtIGZhY3RvcihkZiRibG9jaykKZGYkcG9pbnQgPC0gYXMubnVtZXJpYyhkZiRwb2ludCkKZGYkbm90ZV9pbnRlbnNpdHkgPC0gZmFjdG9yKGRmJG5vdGVfaW50ZW5zaXR5LCBsZXZlbHMgPSBjKCJwaWFubyIsIm1lenpvcGlhbm8iLCJtZXp6b2ZvcnRlIiwiZm9ydGUiKSkKIyByZW1vdmUgZm9ydGlzc2ltbyB0b2tlbnMKZGYgPSBkZlshKGlzLm5hKGRmJG5vdGVfaW50ZW5zaXR5KSAmIGRmJGFjdGl2aXR5PT0ibXVzaWMiKSxdCmRmTm90ZXMgPC0gc3Vic2V0KGRmLGRmJHRva2VuUG9vbGVkID09ICJCYjIifAogICAgICAgICAgICAgICAgICAgIGRmJHRva2VuUG9vbGVkID09ICJCYjMifAogICAgICAgICAgICAgICAgICAgIGRmJHRva2VuUG9vbGVkID09ICJENCJ8CiAgICAgICAgICAgICAgICAgICAgZGYkdG9rZW5Qb29sZWQgPT0gIkYzInwKICAgICAgICAgICAgICAgICAgICBkZiR0b2tlblBvb2xlZCA9PSAiRjQiKQpkZk5vdGVzJHRva2VuUG9vbGVkIDwtIGZhY3RvcihkZk5vdGVzJHRva2VuUG9vbGVkLCBsZXZlbHMgPSBjKCJCYjIiLCJGMyIsIkJiMyIsIkQ0IiwiRjQiKSkKZGZOb3RlcyA8LSBzdWJzZXQoZGZOb3RlcyxkZk5vdGVzJG5vdGVfaW50ZW5zaXR5ID09ICJmb3J0ZSJ8CiAgICAgICAgICAgICAgICAgICAgZGZOb3RlcyRub3RlX2ludGVuc2l0eSA9PSAibWV6em9mb3J0ZSJ8CiAgICAgICAgICAgICAgICAgICAgZGZOb3RlcyRub3RlX2ludGVuc2l0eSA9PSAibWV6em9waWFubyJ8CiAgICAgICAgICAgICAgICAgICAgZGZOb3RlcyRub3RlX2ludGVuc2l0eSA9PSAicGlhbm8iKQpkZk5vdGVzJG5vdGVfaW50ZW5zaXR5IDwtIGZhY3RvcihkZk5vdGVzJG5vdGVfaW50ZW5zaXR5LCBsZXZlbHMgPSBjKCJwaWFubyIsIm1lenpvcGlhbm8iLCJtZXp6b2ZvcnRlIiwiZm9ydGUiKSkKZGZOb3RlcyRub3RlSW50ZW5JbnQgPC0gaW50ZXJhY3Rpb24oZGZOb3RlcyR0b2tlblBvb2xlZCwgZGZOb3RlcyRub3RlX2ludGVuc2l0eSkKZGZOb3RlcyRsYW5nTm90ZUludCA8LSBpbnRlcmFjdGlvbihkZk5vdGVzJG5hdGl2ZV9sZywgZGZOb3RlcyR0b2tlblBvb2xlZCwgZGZOb3RlcyRub3RlX2ludGVuc2l0eSkKZGZOb3RlcyRuYXRpdmVfbGcub3JkIDwtIGFzLm9yZGVyZWQoZGZOb3RlcyRuYXRpdmVfbGcpCmNvbnRyYXN0cyhkZk5vdGVzJG5hdGl2ZV9sZy5vcmQpIDwtICJjb250ci50cmVhdG1lbnQiCmRmTm90ZXMkdG9rZW5Qb29sZWQub3JkIDwtIGFzLm9yZGVyZWQoZGZOb3RlcyR0b2tlblBvb2xlZCkKY29udHJhc3RzKGRmTm90ZXMkdG9rZW5Qb29sZWQub3JkKSA8LSAiY29udHIudHJlYXRtZW50IgpkZk5vdGVzJG5vdGVfaW50ZW5zaXR5Lm9yZCA8LSBhcy5vcmRlcmVkKGRmTm90ZXMkbm90ZV9pbnRlbnNpdHkpCmNvbnRyYXN0cyhkZk5vdGVzJG5vdGVfaW50ZW5zaXR5Lm9yZCkgPC0gImNvbnRyLnRyZWF0bWVudCIKZGZOb3RlcyRsYW5nTm90ZUludC5vcmQgPC0gYXMub3JkZXJlZChkZk5vdGVzJGxhbmdOb3RlSW50KQpjb250cmFzdHMoZGZOb3RlcyRsYW5nTm90ZUludC5vcmQpIDwtICJjb250ci50cmVhdG1lbnQiCmRmTm90ZXMkc3RhcnQgPC0gZGZOb3RlcyRwb2ludHM9PTEKCiMgbWFrZSBjb3B5IG9mIGRmTm90ZXMKZGF0MSA9IGRmTm90ZXMKIyBkYXQxJHByZWRpY3RlZF92YWx1ZXMgPSBwcmVkaWN0KE5vdGVzLmdhbS5BUi5Nb2QyKQoKIyB3aXRoIFNFIC0+IHRha2VzIHZlcnkgbG9uZyEhIQpkYXQxJHByZWRpY3RlZF92YWx1ZXMgPSBwcmVkaWN0KE5vdGVzLmdhbS5BUi5Nb2QyLCBzZS5maXQ9VFJVRSkKCiMgcGxvdCBpbiBwb2xhciBjb29yZGluYXRlcyB1c2luZyBwbG90bHkKZGF0MV9OWkUgPSBkYXQxW2RhdDEkbmF0aXZlX2xnID09ICJOWkUiLF0KZGF0MV9Ub25nYW4gPSBkYXQxW2RhdDEkbmF0aXZlX2xnID09ICJUb25nYW4iLF0KCiMgZXN0aW1hdGUgc21vb3RocyB1c2luZyBSJ3MgZ2VuZXJpYyBwcmVkaWN0LnNtb290aC5zcGxpbmUgZnVuY3Rpb24Kc21vb3RoX05aRT1saXN0KHRoZXRhPXNlcShtaW4oZGF0MV9OWkUkdGhldGFfdW5jdXRfeikqMTgwL3BpLCBtYXgoZGF0MV9OWkUkdGhldGFfdW5jdXRfeikqMTgwL3BpLCBsZW5ndGg9MTAwKSwgcj1wcmVkaWN0KHNtb290aC5zcGxpbmUoZGF0MV9OWkUkdGhldGFfdW5jdXRfeiwgZGF0MV9OWkUkcHJlZGljdGVkX3ZhbHVlcyksCiBzZXEobWluKGRhdDFfTlpFJHRoZXRhX3VuY3V0X3opLCBtYXgoZGF0MV9OWkUkdGhldGFfdW5jdXRfeiksIGxlbmd0aD0xMDApKSR5LCBsaW5lPWxpc3QoY29sb3I9ImJsdWUiLCBkYXNoPSJkYXNoIikpCgpzbW9vdGhfVG9uZ2FuPWxpc3QodGhldGE9c2VxKG1pbihkYXQxX1RvbmdhbiR0aGV0YV91bmN1dF96KSoxODAvcGksIG1heChkYXQxX1RvbmdhbiR0aGV0YV91bmN1dF96KSoxODAvcGksIGxlbmd0aD0xMDApLCByPXByZWRpY3Qoc21vb3RoLnNwbGluZShkYXQxX1RvbmdhbiR0aGV0YV91bmN1dF96LCBkYXQxX1RvbmdhbiRwcmVkaWN0ZWRfdmFsdWVzKSwKIHNlcShtaW4oZGF0MV9Ub25nYW4kdGhldGFfdW5jdXRfeiksIG1heChkYXQxX1RvbmdhbiR0aGV0YV91bmN1dF96KSwgbGVuZ3RoPTEwMCkpJHksIGxpbmU9bGlzdChjb2xvcj0icmVkIiwgZGFzaD0iIikpCgojIHNldCBSaG8gbWF4IHRvIHRoZSBtYXggb2YgdGhlIHByZWRpY3RlZF92YWx1ZXMgKyA1Cm1heF9wcmVkaWN0aW9ucyA9IG1heChtYXgoc21vb3RoX05aRSRyKSwgbWF4KHNtb290aF9Ub25nYW4kcikpCm1heGltdW09bWF4X3ByZWRpY3Rpb25zKzUKcm0obWF4X3ByZWRpY3Rpb25zKQoKcCA9IHBsb3RfbHkodHlwZT0nc2NhdHRlcnBvbGFyJywgbW9kZT0nbGluZXMnKSAlPiUKYWRkX3RyYWNlKHRoZXRhPXNtb290aF9OWkUkdGhldGEsIHI9c21vb3RoX05aRSRyLCBsaW5lPWxpc3QoY29sb3I9c21vb3RoX05aRSRsaW5lJGNvbG9yW1sxXV0sIHdpZHRoPTIuNSwgZGFzaD1zbW9vdGhfTlpFJGxpbmUkZGFzaFtbMV1dKSwgbmFtZT0ib3ZlcmFsbCBhdmVyYWdlIG9mIE5aRSBub3RlcyIpICU+JQogIGFkZF90cmFjZSh0aGV0YT1zbW9vdGhfVG9uZ2FuJHRoZXRhLCByPXNtb290aF9Ub25nYW4kciwgbGluZT1saXN0KGNvbG9yPXNtb290aF9Ub25nYW4kbGluZSRjb2xvcltbMV1dLCB3aWR0aD0yLjUsIGRhc2g9c21vb3RoX1RvbmdhbiRsaW5lJGRhc2hbWzFdXSksIG5hbWU9Im92ZXJhbGwgYXZlcmFnZSBvZiBUb25nYW4gbm90ZXMiKSAlPiUKICBsYXlvdXQocG9sYXI9bGlzdChzZWN0b3I9YygyMCwxNjApLCByYWRpYWxheGlzPWxpc3QoYW5nbGU9OTAsIHJhbmdlPWMoMCxtYXhpbXVtKSksIGFuZ3VsYXJheGlzPWxpc3QodGhldGF1bml0PSdyYWRpYW5zJywgZGlyZWN0aW9uPSJjbG9ja3dpc2UiLCByb3RhdGlvbj0wKSksIHRpdGxlPSJPdmVyYWxsIGF2ZXJhZ2Ugc21vb3RocyBmb3IgTlpFIHZzIFRvbmdhbiBub3RlIHByb2R1Y3Rpb25zIiwgbGVnZW5kPWxpc3Qob3JpZW50YXRpb249ImgiLCB4YW5jaG9yPSJjZW50ZXIiLCB4PTAuNSx5PTAuMDEyKSkKcAppZihzYXZlPT1UUlVFKXsKICBvcmNhKHAsICJGaWd1cmU0LnBkZiIsZm9ybWF0PSJwZGYiKQogIG9yY2EocCwgIkZpZ3VyZTQuanBnIixmb3JtYXQ9ImpwZWciKQp9CnJtKGRhdDEsIGRhdDFfTlpFLCBkYXQxX1RvbmdhbiwgbWF4aW11bSwgc21vb3RoX05aRSwgc21vb3RoX1RvbmdhbikKYGBgCgoKIyMgRmlndXJlIDUgKHByZXZpb3VzbHkgNCkgLT4gSDEKCiMjIyBCYjIgZm9ydGUKCmBgYHtyIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIGVycm9yPUZBTFNFLCBmaWcud2lkdGg9OCwgZmlnLmhlaWdodD01fQpwbG90bHlfc21vb3Roc193X3NpZ19kaWZmKG1vZGVsPSJOb3Rlcy5nYW0uQVIuTW9kMiIsIGNvbmRpdGlvbj0ibGFuZ05vdGVJbnQub3JkIiwgdmFyMT0iQmIyIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyMj0iZm9ydGUiLCB2YWx1ZXM9InRoZXRhX3VuY3V0X3oiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICBsYW5ndWFnZT1jKCJOWkUiLCJUb25nYW4iKSwgZmlsZU5hbWUgPSAiRmlndXJlNShhKSIsIHNhdmU9cHJpbnRQREYpCmBgYAoKIyMjIEYzIG1lenpvZm9ydGUKCmBgYHtyIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIGVycm9yPUZBTFNFLCBmaWcud2lkdGg9OCwgZmlnLmhlaWdodD01fQpwbG90bHlfc21vb3Roc193X3NpZ19kaWZmKG1vZGVsPSJOb3Rlcy5nYW0uQVIuTW9kMiIsIGNvbmRpdGlvbj0ibGFuZ05vdGVJbnQub3JkIiwgdmFyMT0iRjMiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIyPSJtZXp6b2ZvcnRlIiwgdmFsdWVzPSJ0aGV0YV91bmN1dF96IiwKICAgICAgICAgICAgICAgICAgICAgICAgICBsYW5ndWFnZT1jKCJOWkUiLCJUb25nYW4iKSwgLGZpbGVOYW1lID0gIkZpZ3VyZTUoYikiLHNhdmU9cHJpbnRQREYpCmBgYAoKIyMjIEJiMyBtZXp6b2ZvcnRlCgpgYGB7ciB3YXJuaW5nPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCBlcnJvcj1GQUxTRSwgZmlnLndpZHRoPTgsIGZpZy5oZWlnaHQ9NX0KcGxvdGx5X3Ntb290aHNfd19zaWdfZGlmZihtb2RlbD0iTm90ZXMuZ2FtLkFSLk1vZDIiLCBjb25kaXRpb249ImxhbmdOb3RlSW50Lm9yZCIsIHZhcjE9IkJiMyIsIAogICAgICAgICAgICAgICAgICAgICAgICAgIHZhcjI9Im1lenpvZm9ydGUiLCB2YWx1ZXM9InRoZXRhX3VuY3V0X3oiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICBsYW5ndWFnZT1jKCJOWkUiLCJUb25nYW4iKSxmaWxlTmFtZSA9ICJGaWd1cmU1KGMpIixzYXZlPXByaW50UERGKQoKYGBgCgojIyMgSW50ZXJ2YWxzIG9mIHNpZ25pZmljYW50IGRpZmZlcmVuY2UgMTYgb3V0IG9mIDE5IGNvbXBhcmlzb25zCgpgYGB7ciB3YXJuaW5nPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCBlcnJvcj1GQUxTRSwgZmlnLndpZHRoPTgsIGZpZy5oZWlnaHQ9NX0KIyByZWFkIC5jc3YgZmlsZQpzaWdfZGlmZnMgPSByZWFkLmNzdihmaWxlID0gIk5vdGVzLmdhbS5BUi5Nb2QyX2ludGVydmFsc19vZl9zaWduaWZpY2FudF9kaWZmZXJlbmNlcy5jc3YiLCAKICAgICAgICAgICAgICAgICAgICAgaGVhZGVyPVRSVUUsIHJvdy5uYW1lcz0xKQoKIyBHb3QgcmlkIG9mIHRoaXMgcGxvdCEKIyAjIHZpc3VhbGl6ZSBhcmVhcyBvZiBvdmVyYWxsIGRpZmZlcmVuY2UKIyBwMT1wbG90X2x5KHR5cGU9J3NjYXR0ZXJwb2xhcicsIG1vZGU9J2xpbmVzJykgJT4lCiMgICBhZGRfdHJhY2UodGhldGE9c2VxKHNpZ19kaWZmc1siMTdfb3V0X29mXzE5IiwxXSoxODAvcGksIHNpZ19kaWZmc1siMTdfb3V0X29mXzE5IiwyXSoxODAvcGksIAojICAgICAgICAgICAgICAgICAgICAgICBsZW5ndGgub3V0PTIwKSwgcj1jKDAsIHJlcCgzMjAsIDE4KSwgMCksIGxpbmU9bGlzdChjb2xvcj0iYmxhY2siLCB3aWR0aD0wLjUpLCAKIyAgICAgICAgICAgICBmaWxsPSJ0b3NlbGYiLCBmaWxsY29sb3I9cmdiKDAsMCwwLG1heD0yNTUsYWxwaGE9MjUpLCBzaG93bGVnZW5kPUZBTFNFKSAlPiUKIyAgIGFkZF90cmFjZSh0aGV0YT1zZXEoc2lnX2RpZmZzWyIxN19vdXRfb2ZfMTkiLDNdKjE4MC9waSwgc2lnX2RpZmZzWyIxN19vdXRfb2ZfMTkiLDRdKjE4MC9waSwgCiMgICAgICAgICAgICAgICAgICAgICAgIGxlbmd0aC5vdXQ9MjApLCByPWMoMCwgcmVwKDMyMCwgMTgpLCAwKSwgbGluZT1saXN0KGNvbG9yPSJibGFjayIsIHdpZHRoPTAuNSksIAojICAgICAgICAgICAgIGZpbGw9InRvc2VsZiIsIGZpbGxjb2xvcj1yZ2IoMCwwLDAsbWF4PTI1NSxhbHBoYT0yNSksIHNob3dsZWdlbmQ9RkFMU0UpICU+JSAKIyAgIGxheW91dChwb2xhcj1saXN0KHNlY3Rvcj1jKDIwLDE2MCksIHJhZGlhbGF4aXM9bGlzdChhbmdsZT05MCwgcmFuZ2U9YygwLDMyMCkpLAojICAgICAgICAgICAgICAgICAgICAgICAgIGFuZ3VsYXJheGlzPWxpc3QodGhldGF1bml0PSdyYWRpYW5zJywgZGlyZWN0aW9uPSJjbG9ja3dpc2UiLCByb3RhdGlvbj0wKSksIAojICAgICAgICAgIHRpdGxlPXBhc3RlMCgiSW50ZXJ2YWxzIG9mIHNpZ25pZmljYW50IGRpZmZlcmVuY2VzIGZvciAxNyBvdXQgb2YgMTkgY29tcGFyaXNvbnMiKSwgCiMgICAgICAgICAgbGVnZW5kPWxpc3Qob3JpZW50YXRpb249ImgiLCB4YW5jaG9yPSJjZW50ZXIiLCB4PTAuNSx5PTAuMDEyKSkKIyBTeXMuc2xlZXAoMCkKIyBwcmludChwMSkKCnAyPXBsb3RfbHkodHlwZT0nc2NhdHRlcnBvbGFyJywgbW9kZT0nbGluZXMnKSAlPiUKICBhZGRfdHJhY2UodGhldGE9c2VxKHNpZ19kaWZmc1siMTZfb3V0X29mXzE5IiwxXSoxODAvcGksIHNpZ19kaWZmc1siMTZfb3V0X29mXzE5IiwyXSoxODAvcGksIAogICAgICAgICAgICAgICAgICAgICAgbGVuZ3RoLm91dD0yMCksIHI9YygwLCByZXAoMzIwLCAxOCksIDApLCBsaW5lPWxpc3QoY29sb3I9ImJsYWNrIiwgd2lkdGg9MC41KSwgCiAgICAgICAgICAgIGZpbGw9InRvc2VsZiIsIGZpbGxjb2xvcj1yZ2IoMCwwLDAsbWF4PTI1NSxhbHBoYT0yNSksIHNob3dsZWdlbmQ9RkFMU0UpICU+JQogIGFkZF90cmFjZSh0aGV0YT1zZXEoc2lnX2RpZmZzWyIxNl9vdXRfb2ZfMTkiLDNdKjE4MC9waSwgc2lnX2RpZmZzWyIxNl9vdXRfb2ZfMTkiLDRdKjE4MC9waSwgCiAgICAgICAgICAgICAgICAgICAgICBsZW5ndGgub3V0PTIwKSwgcj1jKDAsIHJlcCgzMjAsIDE4KSwgMCksIGxpbmU9bGlzdChjb2xvcj0iYmxhY2siLCB3aWR0aD0wLjUpLCAKICAgICAgICAgICAgZmlsbD0idG9zZWxmIiwgZmlsbGNvbG9yPXJnYigwLDAsMCxtYXg9MjU1LGFscGhhPTI1KSwgc2hvd2xlZ2VuZD1GQUxTRSkgJT4lIAogIGxheW91dChwb2xhcj1saXN0KHNlY3Rvcj1jKDIwLDE2MCksIHJhZGlhbGF4aXM9bGlzdChhbmdsZT05MCwgcmFuZ2U9YygwLDI3MCkpLAogICAgICAgICAgICAgICAgICAgICAgICBhbmd1bGFyYXhpcz1saXN0KHRoZXRhdW5pdD0ncmFkaWFucycsIGRpcmVjdGlvbj0iY2xvY2t3aXNlIiwgcm90YXRpb249MCkpLCAKICAgICAgICAgdGl0bGU9cGFzdGUwKCJJbnRlcnZhbHMgb2Ygc2lnbmlmaWNhbnQgZGlmZmVyZW5jZXMgZm9yIDE2IG91dCBvZiAxOSBjb21wYXJpc29ucyIpLCAKICAgICAgICAgbGVnZW5kPWxpc3Qob3JpZW50YXRpb249ImgiLCB4YW5jaG9yPSJjZW50ZXIiLCB4PTAuNSx5PTAuMDEyKSkKU3lzLnNsZWVwKDApCnByaW50KHAyKQppZihwcmludFBERj09VFJVRSkKewogIG9yY2EocDIsICJGaWd1cmU1KGQpLnBkZiIsZm9ybWF0PSJwZGYiKQogIG9yY2EocDIsICJGaWd1cmU1KGQpLmpwZyIsZm9ybWF0PSJqcGVnIikKfQpybShzaWdfZGlmZnMsIHAxLCBwMikKYGBgCgoKIyMgRmlndXJlIDYgLT4gSDFiCgpgYGB7cn0KIyBkZiBhbHJlYWR5IGxvYWRlZCBhYm92ZQoKZGZTdW1tYXJ5IDwtIGdyb3VwX2J5KGRmLCBzdWJqZWN0LCBwbGF5aW5nX3Byb2ZpY2llbmN5LCBhY3Rpdml0eSwgbmF0aXZlX2xnLCB0b2tlblBvb2xlZCwgdGhldGFfdW5jdXRfel9ncm91cCA9IGN1dCh0aGV0YV91bmN1dF96LGJyZWFrcz0xMDApKSAlPiUgc3VtbWFyaXNlKHJob1ZhciA9IHNkKHJob191bmN1dF96LG5hLnJtPVRSVUUpKQpkZlN1bW1hcnkkdGhldGFfdW5jdXRfeiA9IGFzLmNoYXJhY3RlcihkZlN1bW1hcnkkdGhldGFfdW5jdXRfel9ncm91cCkKZGZTdW1tYXJ5JHRoZXRhX3VuY3V0X3ogPSBnc3ViKCJcXFt8XFxdfFxcKHxcXCkiLCAiIixkZlN1bW1hcnkkdGhldGFfdW5jdXRfeikKZGZTdW1tYXJ5JHRoZXRhX3VuY3V0X3ogPSBzdHJzcGxpdChkZlN1bW1hcnkkdGhldGFfdW5jdXRfeiwiLCIpCmRmU3VtbWFyeSR0aGV0YV91bmN1dF96MiA9IDEKZm9yKGkgaW4gYygxOm5yb3coZGZTdW1tYXJ5KSkpCnsKICBkZlN1bW1hcnkkdGhldGFfdW5jdXRfejJbaV0gPSBtZWFuKGFzLm51bWVyaWModW5saXN0KGRmU3VtbWFyeSR0aGV0YV91bmN1dF96W2ldKSkpCn0KZGZTdW1tYXJ5JHRoZXRhX3VuY3V0X3o9ZGZTdW1tYXJ5JHRoZXRhX3VuY3V0X3oyCmRmU3VtbWFyeSRwbGF5aW5nX3Byb2ZpY2llbmN5Lm9yZCA8LSBhcy5vcmRlcmVkKGRmU3VtbWFyeSRwbGF5aW5nX3Byb2ZpY2llbmN5KQpjb250cmFzdHMoZGZTdW1tYXJ5JHBsYXlpbmdfcHJvZmljaWVuY3kub3JkKSA8LSAiY29udHIudHJlYXRtZW50IgpkZlN1bW1hcnkkYWN0aXZpdHkub3JkIDwtIGFzLm9yZGVyZWQoZGZTdW1tYXJ5JGFjdGl2aXR5KQpjb250cmFzdHMoZGZTdW1tYXJ5JGFjdGl2aXR5Lm9yZCkgPC0gImNvbnRyLnRyZWF0bWVudCIKZGZTdW1tYXJ5JGxhbmdOb3RlSW50IDwtIGludGVyYWN0aW9uKGRmU3VtbWFyeSRuYXRpdmVfbGcsIApkZlN1bW1hcnkkdG9rZW5Qb29sZWQpCmRmU3VtbWFyeSRsYW5nTm90ZUludC5vcmQgPC0gYXMub3JkZXJlZChkZlN1bW1hcnkkbGFuZ05vdGVJbnQpCmNvbnRyYXN0cyhkZlN1bW1hcnkkbGFuZ05vdGVJbnQub3JkKSA8LSAiY29udHIudHJlYXRtZW50IgpkZlN1bW1hcnkkbmF0aXZlX2xnLm9yZCA8LSBhcy5vcmRlcmVkKGRmU3VtbWFyeSRuYXRpdmVfbGcpCmNvbnRyYXN0cyhkZlN1bW1hcnkkbmF0aXZlX2xnLm9yZCkgPC0gImNvbnRyLnRyZWF0bWVudCIKZGZTdW1tYXJ5JHRva2VuUG9vbGVkLm9yZCA8LSBhcy5vcmRlcmVkKGRmU3VtbWFyeSR0b2tlblBvb2xlZCkKY29udHJhc3RzKGRmU3VtbWFyeSR0b2tlblBvb2xlZC5vcmQpIDwtICJjb250ci50cmVhdG1lbnQiCmRmU3VtbWFyeSA9IG5hLm9taXQoZGZTdW1tYXJ5KQoKI2RmU3VtbWFyeSRzdGFydCA8LSBkZlN1bW1hcnkkdGhldGFfdW5jdXRfej09bWluKGRmU3VtbWFyeSR0aGV0YV91bmN1dF96KQoKZGZTdW1tYXJ5JHN0YXJ0ID0gVFJVRQpmb3IoaSBpbiB1bmlxdWUoZGZTdW1tYXJ5JHN1YmplY3QpKQp7CiAgZGZTdWJqZWN0ID0gc3Vic2V0KGRmU3VtbWFyeSxkZlN1bW1hcnkkc3ViamVjdCA9PSBpKQogIGZvcihqIGluIHVuaXF1ZShkZlN1YmplY3QkdG9rZW5Qb29sZWQpKQogIHsKICAgIGRmU3VtbWFyeSRzdGFydFtkZlN1bW1hcnkkc3ViamVjdCA9PSBpICYgZGZTdW1tYXJ5JHRva2VuUG9vbGVkID09IGpdIDwtIAogICAgICBkZlN1bW1hcnkkdGhldGFfdW5jdXRfeltkZlN1bW1hcnkkc3ViamVjdCA9PSBpICYgZGZTdW1tYXJ5JHRva2VuUG9vbGVkID09IGpdID09CiAgICAgIG1pbihkZlN1bW1hcnkkdGhldGFfdW5jdXRfeltkZlN1bW1hcnkkc3ViamVjdCA9PSBpICYgZGZTdW1tYXJ5JHRva2VuUG9vbGVkID09IGpdKQogIH0KfQoKIyBtYWtlIGNvcHkgb2YgZGZOb3RlcwpkYXQxID0gZGZTdW1tYXJ5CmRhdDEkcHJlZGljdGVkX3ZhbHVlcyA9IHByZWRpY3QoVkFSLmdhbS5BUi5Nb2QyKQoKIyBwbG90IGluIHBvbGFyIGNvb3JkaW5hdGVzIHVzaW5nIHBsb3RseQpkYXQxX05aRSA9IGRhdDFbZGF0MSRuYXRpdmVfbGcgPT0gIk5aRSIsXQpkYXQxX1RvbmdhbiA9IGRhdDFbZGF0MSRuYXRpdmVfbGcgPT0gIlRvbmdhbiIsXQoKIyBlc3RpbWF0ZSBzbW9vdGhzIHVzaW5nIFIncyBnZW5lcmljIHByZWRpY3Quc21vb3RoLnNwbGluZSBmdW5jdGlvbgpzbW9vdGhfTlpFPWxpc3QodGhldGE9c2VxKG1pbihkYXQxX05aRSR0aGV0YV91bmN1dF96KSoxODAvcGksIG1heChkYXQxX05aRSR0aGV0YV91bmN1dF96KSoxODAvcGksIGxlbmd0aD0xMDApLCByPXByZWRpY3Qoc21vb3RoLnNwbGluZShkYXQxX05aRSR0aGV0YV91bmN1dF96LCBkYXQxX05aRSRwcmVkaWN0ZWRfdmFsdWVzKSwKIHNlcShtaW4oZGF0MV9OWkUkdGhldGFfdW5jdXRfeiksIG1heChkYXQxX05aRSR0aGV0YV91bmN1dF96KSwgbGVuZ3RoPTEwMCkpJHksIGxpbmU9bGlzdChjb2xvcj0iYmx1ZSIsIGRhc2g9ImRhc2giKSkKCnNtb290aF9Ub25nYW49bGlzdCh0aGV0YT1zZXEobWluKGRhdDFfVG9uZ2FuJHRoZXRhX3VuY3V0X3opKjE4MC9waSwgbWF4KGRhdDFfVG9uZ2FuJHRoZXRhX3VuY3V0X3opKjE4MC9waSwgbGVuZ3RoPTEwMCksIHI9cHJlZGljdChzbW9vdGguc3BsaW5lKGRhdDFfVG9uZ2FuJHRoZXRhX3VuY3V0X3osIGRhdDFfVG9uZ2FuJHByZWRpY3RlZF92YWx1ZXMpLAogc2VxKG1pbihkYXQxX1RvbmdhbiR0aGV0YV91bmN1dF96KSwgbWF4KGRhdDFfVG9uZ2FuJHRoZXRhX3VuY3V0X3opLCBsZW5ndGg9MTAwKSkkeSwgbGluZT1saXN0KGNvbG9yPSJyZWQiLCBkYXNoPSIiKSkKCiMgc2V0IFJobyBtYXggdG8gdGhlIG1heCBvZiB0aGUgcHJlZGljdGVkX3ZhbHVlcyArIDUKbWF4X3ByZWRpY3Rpb25zID0gbWF4KG1heChzbW9vdGhfTlpFJHIpLCBtYXgoc21vb3RoX1RvbmdhbiRyKSkKbWF4aW11bT1tYXhfcHJlZGljdGlvbnMrMQpybShtYXhfcHJlZGljdGlvbnMpCgpwID0gcGxvdF9seSh0eXBlPSdzY2F0dGVycG9sYXInLCBtb2RlPSdsaW5lcycpICU+JQphZGRfdHJhY2UodGhldGE9c21vb3RoX05aRSR0aGV0YSwgcj1zbW9vdGhfTlpFJHIsIGxpbmU9bGlzdChjb2xvcj1zbW9vdGhfTlpFJGxpbmUkY29sb3JbWzFdXSwgd2lkdGg9Mi41LCBkYXNoPXNtb290aF9OWkUkbGluZSRkYXNoW1sxXV0pLCBuYW1lPSJvdmVyYWxsIGF2ZXJhZ2Ugb2YgTlpFIG5vdGVzIikgJT4lCiAgYWRkX3RyYWNlKHRoZXRhPXNtb290aF9Ub25nYW4kdGhldGEsIHI9c21vb3RoX1RvbmdhbiRyLCBsaW5lPWxpc3QoY29sb3I9c21vb3RoX1RvbmdhbiRsaW5lJGNvbG9yW1sxXV0sIHdpZHRoPTIuNSwgZGFzaD1zbW9vdGhfVG9uZ2FuJGxpbmUkZGFzaFtbMV1dKSwgbmFtZT0ib3ZlcmFsbCBhdmVyYWdlIG9mIFRvbmdhbiBub3RlcyIpICU+JQogIGxheW91dChwb2xhcj1saXN0KHNlY3Rvcj1jKDIwLDE2MCksIHJhZGlhbGF4aXM9bGlzdChhbmdsZT05MCwgcmFuZ2U9YygwLG1heGltdW0pKSwgYW5ndWxhcmF4aXM9bGlzdCh0aGV0YXVuaXQ9J3JhZGlhbnMnLCBkaXJlY3Rpb249ImNsb2Nrd2lzZSIsIHJvdGF0aW9uPTApKSwgdGl0bGU9Ik92ZXJhbGwgYXZlcmFnZSBzbW9vdGhzIGZvciBOWkUgdnMgVG9uZ2FuIG5vdGUgcHJvZHVjdGlvbnMiLCBsZWdlbmQ9bGlzdChvcmllbnRhdGlvbj0iaCIsIHhhbmNob3I9ImNlbnRlciIsIHg9MC41LHk9MC4wMTIpKQpwCmlmKHByaW50UERGPT1UUlVFKQp7CiAgb3JjYShwLCAiRmlndXJlNi5wZGYiLGZvcm1hdD0icGRmIikKICBvcmNhKHAsICJGaWd1cmU2LmpwZyIsZm9ybWF0PSJqcGVnIikKfQpybShkYXQxLCBkYXQxX05aRSwgZGF0MV9Ub25nYW4sIG1heGltdW0sIHNtb290aF9OWkUsIHNtb290aF9Ub25nYW4pCmBgYAoKCiMjIEZpZ3VyZSA3IC0+IEgyIHZvd2VscyBhbmQgbm90ZXMgTlpFCgojIyMgQWxsIE5aRSB2b3dlbHMKCmBgYHtyIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIGVycm9yPUZBTFNFLCBmaWcud2lkdGg9OCwgZmlnLmhlaWdodD01fQojIGRlZmluZSBjb2xvcnMgZnJvbSBQaEQgdGhlc2lzClJFRDAgPSAocmdiKDIxMywxMywxMSwgMjU1LCBtYXhDb2xvclZhbHVlPTI1NSkpCkJST1dOMCA9IChyZ2IoMTIzLDczLDU1LDI1NSwgbWF4Q29sb3JWYWx1ZT0yNTUpKQpQVVJQTEUwID0gKHJnYigxNDMsNzIsMTgzLDI1NSwgbWF4Q29sb3JWYWx1ZT0yNTUpKQpHUkFZMCA9IChyZ2IoMTA4LDEwOCwxMDgsMjU1LCBtYXhDb2xvclZhbHVlPTI1NSkpCkdSRUVOMCA9IChyZ2IoMCwxNTEsNTUsMjU1LCBtYXhDb2xvclZhbHVlPTI1NSkpCk9SQU5HRTAgPSAocmdiKDI1NSwxMjMsMCwyNTUsIG1heENvbG9yVmFsdWU9MjU1KSkKUElOSzAgPSAocmdiKDIyNCwxMzAsMTgwLDI1NSwgbWF4Q29sb3JWYWx1ZT0yNTUpKQpURUFMMCA9IChyZ2IoMCwxNzUsMTk1LDI1NSwgbWF4Q29sb3JWYWx1ZT0yNTUpKQpHT0xEMCA9IChyZ2IoMTcyLDE4MSwwLDI1NSwgbWF4Q29sb3JWYWx1ZT0yNTUpKQpsaWdodF9ibHVlPXJnYigwLDExNywyMjAsMjU1LG1heENvbG9yVmFsdWU9MjU1KQpibGFjaz1yZ2IoMjUsMjUsMjUsMjU1LG1heENvbG9yVmFsdWU9MjU1KQpwaW5rPXJnYigxOTQsMCwxMzYsMjU1LG1heENvbG9yVmFsdWU9MjU1KQpkYXJrX2JsdWU9cmdiKDAsNTEsMTI4LDI1NSxtYXhDb2xvclZhbHVlPTI1NSkKZGFya19yZWQ9cmdiKDE1MywwLDAsMjU1LG1heENvbG9yVmFsdWU9MjU1KQoKIyBjb3JyZWN0IG9yZGVyCmNvbG9ycyA9IGMoT1JBTkdFMCwgZGFya19ibHVlLCBHUkVFTjAsIGxpZ2h0X2JsdWUsIFBJTkswLCBHT0xEMCwgQlJPV04wLCBURUFMMCwgR1JBWTAsIGRhcmtfcmVkLAogICAgICAgICAgIFJFRDAsIFBVUlBMRTAsIHBpbmspCgojIHJ1biBwbG90X3Ntb290aCB0byBncmFiIHZhbHVlcyBmb3IgZml0LCB1cHBlciAmIGxvd2VyIGJvdW5kcwpwMT1wbG90X3Ntb290aCh4PU5aRS5nYW0uQVIuTW9kMiwgdmlldz0idGhldGFfdW5jdXRfeiIsIGNvbmQ9bGlzdCh0b2tlblBvb2xlZC5vcmQ9ImnLkCIpLCBybS5yYW5lZj1UUlVFKQpwMj1wbG90X3Ntb290aCh4PU5aRS5nYW0uQVIuTW9kMiwgdmlldz0idGhldGFfdW5jdXRfeiIsIGNvbmQ9bGlzdCh0b2tlblBvb2xlZC5vcmQ9ImUiKSwgcm0ucmFuZWY9VFJVRSkKcDM9cGxvdF9zbW9vdGgoeD1OWkUuZ2FtLkFSLk1vZDIsIHZpZXc9InRoZXRhX3VuY3V0X3oiLCBjb25kPWxpc3QodG9rZW5Qb29sZWQub3JkPSLKicuQIiksIHJtLnJhbmVmPVRSVUUpCnA0PXBsb3Rfc21vb3RoKHg9TlpFLmdhbS5BUi5Nb2QyLCB2aWV3PSJ0aGV0YV91bmN1dF96IiwgY29uZD1saXN0KHRva2VuUG9vbGVkLm9yZD0iyZsiKSwgcm0ucmFuZWY9VFJVRSkKcDU9cGxvdF9zbW9vdGgoeD1OWkUuZ2FtLkFSLk1vZDIsIHZpZXc9InRoZXRhX3VuY3V0X3oiLCBjb25kPWxpc3QodG9rZW5Qb29sZWQub3JkPSLJtcuQIiksIHJtLnJhbmVmPVRSVUUpCnA2PXBsb3Rfc21vb3RoKHg9TlpFLmdhbS5BUi5Nb2QyLCB2aWV3PSJ0aGV0YV91bmN1dF96IiwgY29uZD1saXN0KHRva2VuUG9vbGVkLm9yZD0iyZgiKSwgcm0ucmFuZWY9VFJVRSkKcDc9cGxvdF9zbW9vdGgoeD1OWkUuZ2FtLkFSLk1vZDIsIHZpZXc9InRoZXRhX3VuY3V0X3oiLCBjb25kPWxpc3QodG9rZW5Qb29sZWQub3JkPSLJmSIpLCBybS5yYW5lZj1UUlVFKQpwOD1wbG90X3Ntb290aCh4PU5aRS5nYW0uQVIuTW9kMiwgdmlldz0idGhldGFfdW5jdXRfeiIsIGNvbmQ9bGlzdCh0b2tlblBvb2xlZC5vcmQ9IsqKIiksIHJtLnJhbmVmPVRSVUUpCnA5PXBsb3Rfc21vb3RoKHg9TlpFLmdhbS5BUi5Nb2QyLCB2aWV3PSJ0aGV0YV91bmN1dF96IiwgY29uZD1saXN0KHRva2VuUG9vbGVkLm9yZD0iyZkjIiksIHJtLnJhbmVmPVRSVUUpCnAxMD1wbG90X3Ntb290aCh4PU5aRS5nYW0uQVIuTW9kMiwgdmlldz0idGhldGFfdW5jdXRfeiIsIGNvbmQ9bGlzdCh0b2tlblBvb2xlZC5vcmQ9IsmQIiksIHJtLnJhbmVmPVRSVUUpCnAxMT1wbG90X3Ntb290aCh4PU5aRS5nYW0uQVIuTW9kMiwgdmlldz0idGhldGFfdW5jdXRfeiIsIGNvbmQ9bGlzdCh0b2tlblBvb2xlZC5vcmQ9IsmQy5AiKSwgcm0ucmFuZWY9VFJVRSkKcDEyPXBsb3Rfc21vb3RoKHg9TlpFLmdhbS5BUi5Nb2QyLCB2aWV3PSJ0aGV0YV91bmN1dF96IiwgY29uZD1saXN0KHRva2VuUG9vbGVkLm9yZD0iyZIiKSwgcm0ucmFuZWY9VFJVRSkKcDEzPXBsb3Rfc21vb3RoKHg9TlpFLmdhbS5BUi5Nb2QyLCB2aWV3PSJ0aGV0YV91bmN1dF96IiwgY29uZD1saXN0KHRva2VuUG9vbGVkLm9yZD0ib8uQIiksIHJtLnJhbmVmPVRSVUUpCgpzbW9vdGhfbmFtZXM9YygiRkxFRUNFIC9py5AvIiwiRFJFU1MgL2UvIiwiR09PU0UgL8qJy5AvIiwiVFJBUCAvyZsvIiwiTlVSU0UgL8m1y5AvIiwiS0lUIC/JmC8iLAogICAgICAgICAgICAgICAibm9uLWZpbmFsIHNjaHdhIC/JmS8iLCJGT09UIC/Kii8iLCJmaW5hbCBzY2h3YSAvyZkjLyIsIlNUUlVUIC/JkC8iLCJTVEFSVCAvyZDLkC8iLAogICAgICAgICAgICAgICAiTE9UIC/Jki8iLCJUSE9VR0hUIC9vy5AvIikKCiMgIyBzZXQgUmhvIG1heCB0byB0aGUgbWF4IG9mIHRoZSBmaXQgKyBoYWxmIHRoZSBkaWZmZXJlbmNlIGJldHdlZW4gbWF4IG9mIHRoZSBmaXQgYW5kIHRoZSB1cHBlciBsaW1pdAojIG1heF91bCA9IG1heChwMSRmdiR1bCwgcDIkZnYkdWwsIHAzJGZ2JHVsLCBwNCRmdiR1bCwgcDUkZnYkdWwsIHA2JGZ2JHVsLCBwNyRmdiR1bCwgcDgkZnYkdWwsIHA5JGZ2JHVsLCBwMTAkZnYkdWwsIHAxMSRmdiR1bCwgcDEyJGZ2JHVsLCBwMTMkZnYkdWwpCiMgbWF4X2ZpdCA9IG1heChwMSRmdiRmaXQsIHAyJGZ2JGZpdCwgcDMkZnYkZml0LCBwNCRmdiRmaXQsIHA1JGZ2JGZpdCwgcDYkZnYkZml0LCBwNyRmdiRmaXQsIHA4JGZ2JGZpdCwgcDkkZnYkZml0LCBwMTAkZnYkZml0LCBwMTEkZnYkZml0LCBwMTIkZnYkZml0LCBwMTMkZnYkZml0KQojIG1heGltdW09bWF4X2ZpdCsoKG1heF91bC1tYXhfZml0KS8yKQojIHJtKG1heF91bCwgbWF4X2ZpdCkKIyAKIyAjIHBsb3QgaW4gcG9sYXIgY29vcmRpbmF0ZXMgd2l0aCBjb25maWRlbmNlIGJvdW5kcwojIHBsb3QxPXBsb3RfbHkodHlwZT0nc2NhdHRlcnBvbGFyJywgbW9kZT0nbGluZXMnKSAlPiUKIyAgIGFkZF90cmFjZSh0aGV0YT1wMSRmdiR0aGV0YV91bmN1dF96KjE4MC9waSwgcj1wMSRmdiRmaXQsIGxpbmU9bGlzdChjb2xvcj1jb2xvcnNbMV0sIGRhc2g9ImRhc2giLCB3aWR0aD0yLjUpLCBuYW1lPXNtb290aF9uYW1lc1sxXSkgJT4lCiMgICBhZGRfdHJhY2UodGhldGE9cDEkZnYkdGhldGFfdW5jdXRfeioxODAvcGksIHI9cDEkZnYkdWwsIGxpbmU9bGlzdChjb2xvcj1jb2xvcnNbMV0sIGRhc2g9ImRhc2giLCB3aWR0aD0wLjUpLCBzaG93bGVnZW5kPUZBTFNFKSAlPiUKIyAgIGFkZF90cmFjZSh0aGV0YT1wMSRmdiR0aGV0YV91bmN1dF96KjE4MC9waSwgcj1wMSRmdiRsbCwgbGluZT1saXN0KGNvbG9yPWNvbG9yc1sxXSwgZGFzaD0iZGFzaCIsIHdpZHRoPTAuNSksIHNob3dsZWdlbmQ9RkFMU0UpICU+JQojICAgYWRkX3RyYWNlKHRoZXRhPXAyJGZ2JHRoZXRhX3VuY3V0X3oqMTgwL3BpLCByPXAyJGZ2JGZpdCwgbGluZT1saXN0KGNvbG9yPWNvbG9yc1syXSwgd2lkdGg9Mi41KSwKIyAgICAgICAgICAgICBuYW1lPXNtb290aF9uYW1lc1syXSkgJT4lCiMgICBhZGRfdHJhY2UodGhldGE9cDIkZnYkdGhldGFfdW5jdXRfeioxODAvcGksIHI9cDIkZnYkdWwsIGxpbmU9bGlzdChjb2xvcj1jb2xvcnNbMl0sIGRhc2g9ImRvdCIsIHdpZHRoPTAuNSksIHNob3dsZWdlbmQ9RkFMU0UpICU+JQojICAgYWRkX3RyYWNlKHRoZXRhPXAyJGZ2JHRoZXRhX3VuY3V0X3oqMTgwL3BpLCByPXAyJGZ2JGxsLCBsaW5lPWxpc3QoY29sb3I9Y29sb3JzWzJdLCBkYXNoPSJkb3QiLCB3aWR0aD0wLjUpLCBzaG93bGVnZW5kPUZBTFNFKSAlPiUKIyAgIGFkZF90cmFjZSh0aGV0YT1wMyRmdiR0aGV0YV91bmN1dF96KjE4MC9waSwgcj1wMyRmdiRmaXQsIGxpbmU9bGlzdChjb2xvcj1jb2xvcnNbM10sIHdpZHRoPTIuNSksCiMgICAgICAgICAgICAgbmFtZT1zbW9vdGhfbmFtZXNbM10pICU+JQojICAgYWRkX3RyYWNlKHRoZXRhPXAzJGZ2JHRoZXRhX3VuY3V0X3oqMTgwL3BpLCByPXAzJGZ2JHVsLCBsaW5lPWxpc3QoY29sb3I9Y29sb3JzWzNdLCBkYXNoPSJkb3QiLCB3aWR0aD0wLjUpLCBzaG93bGVnZW5kPUZBTFNFKSAlPiUKIyAgIGFkZF90cmFjZSh0aGV0YT1wMyRmdiR0aGV0YV91bmN1dF96KjE4MC9waSwgcj1wMyRmdiRsbCwgbGluZT1saXN0KGNvbG9yPWNvbG9yc1szXSwgZGFzaD0iZG90Iiwgd2lkdGg9MC41KSwgc2hvd2xlZ2VuZD1GQUxTRSkgJT4lCiMgICBhZGRfdHJhY2UodGhldGE9cDQkZnYkdGhldGFfdW5jdXRfeioxODAvcGksIHI9cDQkZnYkZml0LCBsaW5lPWxpc3QoY29sb3I9Y29sb3JzWzRdLCBkYXNoPSJkYXNoIiwgd2lkdGg9Mi41KSwgbmFtZT1zbW9vdGhfbmFtZXNbNF0pICU+JQojICAgYWRkX3RyYWNlKHRoZXRhPXA0JGZ2JHRoZXRhX3VuY3V0X3oqMTgwL3BpLCByPXA0JGZ2JHVsLCBsaW5lPWxpc3QoY29sb3I9Y29sb3JzWzRdLCBkYXNoPSJkYXNoIiwgd2lkdGg9MC41KSwgc2hvd2xlZ2VuZD1GQUxTRSkgJT4lCiMgICBhZGRfdHJhY2UodGhldGE9cDQkZnYkdGhldGFfdW5jdXRfeioxODAvcGksIHI9cDQkZnYkbGwsIGxpbmU9bGlzdChjb2xvcj1jb2xvcnNbNF0sIGRhc2g9ImRhc2giLCB3aWR0aD0wLjUpLCBzaG93bGVnZW5kPUZBTFNFKSAlPiUKIyAgIGFkZF90cmFjZSh0aGV0YT1wNSRmdiR0aGV0YV91bmN1dF96KjE4MC9waSwgcj1wNSRmdiRmaXQsIGxpbmU9bGlzdChjb2xvcj1jb2xvcnNbNV0sIHdpZHRoPTIuNSksCiMgICAgICAgICAgICAgbmFtZT1zbW9vdGhfbmFtZXNbNV0pICU+JQojICAgYWRkX3RyYWNlKHRoZXRhPXA1JGZ2JHRoZXRhX3VuY3V0X3oqMTgwL3BpLCByPXA1JGZ2JHVsLCBsaW5lPWxpc3QoY29sb3I9Y29sb3JzWzVdLCBkYXNoPSJkb3QiLCB3aWR0aD0wLjUpLCBzaG93bGVnZW5kPUZBTFNFKSAlPiUKIyAgIGFkZF90cmFjZSh0aGV0YT1wNSRmdiR0aGV0YV91bmN1dF96KjE4MC9waSwgcj1wNSRmdiRsbCwgbGluZT1saXN0KGNvbG9yPWNvbG9yc1s1XSwgZGFzaD0iZG90Iiwgd2lkdGg9MC41KSwgc2hvd2xlZ2VuZD1GQUxTRSkgJT4lCiMgICBhZGRfdHJhY2UodGhldGE9cDYkZnYkdGhldGFfdW5jdXRfeioxODAvcGksIHI9cDYkZnYkZml0LCBsaW5lPWxpc3QoY29sb3I9Y29sb3JzWzZdLCBkYXNoPSJkYXNoIiwgd2lkdGg9Mi41KSwgbmFtZT1zbW9vdGhfbmFtZXNbNl0pICU+JQojICAgYWRkX3RyYWNlKHRoZXRhPXA2JGZ2JHRoZXRhX3VuY3V0X3oqMTgwL3BpLCByPXA2JGZ2JHVsLCBsaW5lPWxpc3QoY29sb3I9Y29sb3JzWzZdLCBkYXNoPSJkYXNoIiwgd2lkdGg9MC41KSwgc2hvd2xlZ2VuZD1GQUxTRSkgJT4lCiMgICBhZGRfdHJhY2UodGhldGE9cDYkZnYkdGhldGFfdW5jdXRfeioxODAvcGksIHI9cDYkZnYkbGwsIGxpbmU9bGlzdChjb2xvcj1jb2xvcnNbNl0sIGRhc2g9ImRhc2giLCB3aWR0aD0wLjUpLCBzaG93bGVnZW5kPUZBTFNFKSAlPiUKIyAgIGFkZF90cmFjZSh0aGV0YT1wNyRmdiR0aGV0YV91bmN1dF96KjE4MC9waSwgcj1wNyRmdiRmaXQsIGxpbmU9bGlzdChjb2xvcj1jb2xvcnNbN10sIHdpZHRoPTIuNSksCiMgICAgICAgICAgICAgbmFtZT1zbW9vdGhfbmFtZXNbN10pICU+JQojICAgYWRkX3RyYWNlKHRoZXRhPXA3JGZ2JHRoZXRhX3VuY3V0X3oqMTgwL3BpLCByPXA3JGZ2JHVsLCBsaW5lPWxpc3QoY29sb3I9Y29sb3JzWzddLCBkYXNoPSJkb3QiLCB3aWR0aD0wLjUpLCBzaG93bGVnZW5kPUZBTFNFKSAlPiUKIyAgIGFkZF90cmFjZSh0aGV0YT1wNyRmdiR0aGV0YV91bmN1dF96KjE4MC9waSwgcj1wNyRmdiRsbCwgbGluZT1saXN0KGNvbG9yPWNvbG9yc1s3XSwgZGFzaD0iZG90Iiwgd2lkdGg9MC41KSwgc2hvd2xlZ2VuZD1GQUxTRSkgJT4lCiMgICBhZGRfdHJhY2UodGhldGE9cDgkZnYkdGhldGFfdW5jdXRfeioxODAvcGksIHI9cDgkZnYkZml0LCBsaW5lPWxpc3QoY29sb3I9Y29sb3JzWzhdLCBkYXNoPSJkYXNoIiwgd2lkdGg9Mi41KSwgbmFtZT1zbW9vdGhfbmFtZXNbOF0pICU+JQojICAgYWRkX3RyYWNlKHRoZXRhPXA4JGZ2JHRoZXRhX3VuY3V0X3oqMTgwL3BpLCByPXA4JGZ2JHVsLCBsaW5lPWxpc3QoY29sb3I9Y29sb3JzWzhdLCBkYXNoPSJkYXNoIiwgd2lkdGg9MC41KSwgc2hvd2xlZ2VuZD1GQUxTRSkgJT4lCiMgICBhZGRfdHJhY2UodGhldGE9cDgkZnYkdGhldGFfdW5jdXRfeioxODAvcGksIHI9cDgkZnYkbGwsIGxpbmU9bGlzdChjb2xvcj1jb2xvcnNbOF0sIGRhc2g9ImRhc2giLCB3aWR0aD0wLjUpLCBzaG93bGVnZW5kPUZBTFNFKSAlPiUKIyAgIGFkZF90cmFjZSh0aGV0YT1wOSRmdiR0aGV0YV91bmN1dF96KjE4MC9waSwgcj1wOSRmdiRmaXQsIGxpbmU9bGlzdChjb2xvcj1jb2xvcnNbOV0sIHdpZHRoPTIuNSksCiMgICAgICAgICAgICAgbmFtZT1zbW9vdGhfbmFtZXNbOV0pICU+JQojICAgYWRkX3RyYWNlKHRoZXRhPXA5JGZ2JHRoZXRhX3VuY3V0X3oqMTgwL3BpLCByPXA5JGZ2JHVsLCBsaW5lPWxpc3QoY29sb3I9Y29sb3JzWzldLCBkYXNoPSJkb3QiLCB3aWR0aD0wLjUpLCBzaG93bGVnZW5kPUZBTFNFKSAlPiUKIyAgIGFkZF90cmFjZSh0aGV0YT1wOSRmdiR0aGV0YV91bmN1dF96KjE4MC9waSwgcj1wOSRmdiRsbCwgbGluZT1saXN0KGNvbG9yPWNvbG9yc1s5XSwgZGFzaD0iZG90Iiwgd2lkdGg9MC41KSwgc2hvd2xlZ2VuZD1GQUxTRSkgJT4lCiMgICBhZGRfdHJhY2UodGhldGE9cDEwJGZ2JHRoZXRhX3VuY3V0X3oqMTgwL3BpLCByPXAxMCRmdiRmaXQsIGxpbmU9bGlzdChjb2xvcj1jb2xvcnNbMTBdLCB3aWR0aD0yLjUpLAojICAgICAgICAgICAgIG5hbWU9c21vb3RoX25hbWVzWzEwXSkgJT4lCiMgICBhZGRfdHJhY2UodGhldGE9cDEwJGZ2JHRoZXRhX3VuY3V0X3oqMTgwL3BpLCByPXAxMCRmdiR1bCwgbGluZT1saXN0KGNvbG9yPWNvbG9yc1sxMF0sIGRhc2g9ImRvdCIsIHdpZHRoPTAuNSksIHNob3dsZWdlbmQ9RkFMU0UpICU+JQojICAgYWRkX3RyYWNlKHRoZXRhPXAxMCRmdiR0aGV0YV91bmN1dF96KjE4MC9waSwgcj1wMTAkZnYkbGwsIGxpbmU9bGlzdChjb2xvcj1jb2xvcnNbMTBdLCBkYXNoPSJkb3QiLCB3aWR0aD0wLjUpLCBzaG93bGVnZW5kPUZBTFNFKSAlPiUKIyAgIGFkZF90cmFjZSh0aGV0YT1wMTEkZnYkdGhldGFfdW5jdXRfeioxODAvcGksIHI9cDExJGZ2JGZpdCwgbGluZT1saXN0KGNvbG9yPWNvbG9yc1sxMV0sIHdpZHRoPTIuNSksCiMgICAgICAgICAgICAgbmFtZT1zbW9vdGhfbmFtZXNbMTFdKSAlPiUKIyAgIGFkZF90cmFjZSh0aGV0YT1wMTEkZnYkdGhldGFfdW5jdXRfeioxODAvcGksIHI9cDExJGZ2JHVsLCBsaW5lPWxpc3QoY29sb3I9Y29sb3JzWzExXSwgZGFzaD0iZG90Iiwgd2lkdGg9MC41KSwgc2hvd2xlZ2VuZD1GQUxTRSkgJT4lCiMgICBhZGRfdHJhY2UodGhldGE9cDExJGZ2JHRoZXRhX3VuY3V0X3oqMTgwL3BpLCByPXAxMSRmdiRsbCwgbGluZT1saXN0KGNvbG9yPWNvbG9yc1sxMV0sIGRhc2g9ImRvdCIsIHdpZHRoPTAuNSksIHNob3dsZWdlbmQ9RkFMU0UpICU+JQojICAgYWRkX3RyYWNlKHRoZXRhPXAxMiRmdiR0aGV0YV91bmN1dF96KjE4MC9waSwgcj1wMTIkZnYkZml0LCBsaW5lPWxpc3QoY29sb3I9Y29sb3JzWzEyXSwgZGFzaD0iZGFzaCIsIHdpZHRoPTIuNSksIG5hbWU9c21vb3RoX25hbWVzWzEyXSkgJT4lCiMgICBhZGRfdHJhY2UodGhldGE9cDEyJGZ2JHRoZXRhX3VuY3V0X3oqMTgwL3BpLCByPXAxMiRmdiR1bCwgbGluZT1saXN0KGNvbG9yPWNvbG9yc1sxMl0sIGRhc2g9ImRhc2giLCB3aWR0aD0wLjUpLCBzaG93bGVnZW5kPUZBTFNFKSAlPiUKIyAgIGFkZF90cmFjZSh0aGV0YT1wMTIkZnYkdGhldGFfdW5jdXRfeioxODAvcGksIHI9cDEyJGZ2JGxsLCBsaW5lPWxpc3QoY29sb3I9Y29sb3JzWzEyXSwgZGFzaD0iZGFzaCIsIHdpZHRoPTAuNSksIHNob3dsZWdlbmQ9RkFMU0UpICU+JQojICAgYWRkX3RyYWNlKHRoZXRhPXAxMyRmdiR0aGV0YV91bmN1dF96KjE4MC9waSwgcj1wMTMkZnYkZml0LCBsaW5lPWxpc3QoY29sb3I9Y29sb3JzWzEzXSwgd2lkdGg9Mi41KSwKIyAgICAgICAgICAgICBuYW1lPXNtb290aF9uYW1lc1sxM10pICU+JQojICAgYWRkX3RyYWNlKHRoZXRhPXAxMyRmdiR0aGV0YV91bmN1dF96KjE4MC9waSwgcj1wMTMkZnYkdWwsIGxpbmU9bGlzdChjb2xvcj1jb2xvcnNbMTNdLCBkYXNoPSJkb3QiLCB3aWR0aD0wLjUpLCBzaG93bGVnZW5kPUZBTFNFKSAlPiUKIyAgIGFkZF90cmFjZSh0aGV0YT1wMTMkZnYkdGhldGFfdW5jdXRfeioxODAvcGksIHI9cDEzJGZ2JGxsLCBsaW5lPWxpc3QoY29sb3I9Y29sb3JzWzEzXSwgZGFzaD0iZG90Iiwgd2lkdGg9MC41KSwgc2hvd2xlZ2VuZD1GQUxTRSkgJT4lCiMgICBsYXlvdXQocG9sYXI9bGlzdChzZWN0b3I9YygyMCwxNjApLCByYWRpYWxheGlzPWxpc3QoYW5nbGU9OTAsIHJhbmdlPWMoMCxtYXhpbXVtKSksCiMgICAgICAgICAgICAgICAgICAgICBhbmd1bGFyYXhpcz1saXN0KHRoZXRhdW5pdD0ncmFkaWFucycsIGRpcmVjdGlvbj0iY2xvY2t3aXNlIiwgcm90YXRpb249MCkpLAojICAgICAgICAgIHRpdGxlPSJBbGwgdm93ZWxzIHByb2R1Y2VkIGJ5IE5aRSBzcGVha2VycyIpCiMgcGxvdDEKCiMgc2V0IFJobyBtYXggdG8gdGhlIG1heCBvZiB0aGUgZml0ICsgNQptYXhfZml0ID0gbWF4KHAxJGZ2JGZpdCwgcDIkZnYkZml0LCBwMyRmdiRmaXQsIHA0JGZ2JGZpdCwgcDUkZnYkZml0LCBwNiRmdiRmaXQsIHA3JGZ2JGZpdCwgcDgkZnYkZml0LCBwOSRmdiRmaXQsIHAxMCRmdiRmaXQsIHAxMSRmdiRmaXQsIHAxMiRmdiRmaXQsIHAxMyRmdiRmaXQpCm1heGltdW09bWF4X2ZpdCs1CnJtKG1heF9maXQpCgojIHBsb3QgaW4gcG9sYXIgY29vcmRpbmF0ZXMgd2l0aG91dCBjb25maWRlbmNlIGJvdW5kcwpwbG90Mj1wbG90X2x5KHR5cGU9J3NjYXR0ZXJwb2xhcicsIG1vZGU9J2xpbmVzJykgJT4lCiAgYWRkX3RyYWNlKHRoZXRhPXAxJGZ2JHRoZXRhX3VuY3V0X3oqMTgwL3BpLCByPXAxJGZ2JGZpdCwgbGluZT1saXN0KGNvbG9yPWNvbG9yc1sxXSwgZGFzaD0iZGFzaCIsIHdpZHRoPTIuNSksIG5hbWU9c21vb3RoX25hbWVzWzFdKSAlPiUKICBhZGRfdHJhY2UodGhldGE9cDIkZnYkdGhldGFfdW5jdXRfeioxODAvcGksIHI9cDIkZnYkZml0LCBsaW5lPWxpc3QoY29sb3I9Y29sb3JzWzJdLCB3aWR0aD0yLjUpLAogICAgICAgICAgICBuYW1lPXNtb290aF9uYW1lc1syXSkgJT4lCiAgYWRkX3RyYWNlKHRoZXRhPXAzJGZ2JHRoZXRhX3VuY3V0X3oqMTgwL3BpLCByPXAzJGZ2JGZpdCwgbGluZT1saXN0KGNvbG9yPWNvbG9yc1szXSwgd2lkdGg9Mi41KSwKICAgICAgICAgICAgbmFtZT1zbW9vdGhfbmFtZXNbM10pICU+JQogIGFkZF90cmFjZSh0aGV0YT1wNCRmdiR0aGV0YV91bmN1dF96KjE4MC9waSwgcj1wNCRmdiRmaXQsIGxpbmU9bGlzdChjb2xvcj1jb2xvcnNbNF0sIGRhc2g9ImRhc2giLCB3aWR0aD0yLjUpLCBuYW1lPXNtb290aF9uYW1lc1s0XSkgJT4lCiAgYWRkX3RyYWNlKHRoZXRhPXA1JGZ2JHRoZXRhX3VuY3V0X3oqMTgwL3BpLCByPXA1JGZ2JGZpdCwgbGluZT1saXN0KGNvbG9yPWNvbG9yc1s1XSwgd2lkdGg9Mi41KSwKICAgICAgICAgICAgbmFtZT1zbW9vdGhfbmFtZXNbNV0pICU+JQogIGFkZF90cmFjZSh0aGV0YT1wNiRmdiR0aGV0YV91bmN1dF96KjE4MC9waSwgcj1wNiRmdiRmaXQsIGxpbmU9bGlzdChjb2xvcj1jb2xvcnNbNl0sIGRhc2g9ImRhc2giLCB3aWR0aD0yLjUpLCBuYW1lPXNtb290aF9uYW1lc1s2XSkgJT4lCiAgYWRkX3RyYWNlKHRoZXRhPXA3JGZ2JHRoZXRhX3VuY3V0X3oqMTgwL3BpLCByPXA3JGZ2JGZpdCwgbGluZT1saXN0KGNvbG9yPWNvbG9yc1s3XSwgd2lkdGg9Mi41KSwKICAgICAgICAgICAgbmFtZT1zbW9vdGhfbmFtZXNbN10pICU+JQogIGFkZF90cmFjZSh0aGV0YT1wOCRmdiR0aGV0YV91bmN1dF96KjE4MC9waSwgcj1wOCRmdiRmaXQsIGxpbmU9bGlzdChjb2xvcj1jb2xvcnNbOF0sIGRhc2g9ImRhc2giLCB3aWR0aD0yLjUpLCBuYW1lPXNtb290aF9uYW1lc1s4XSkgJT4lCiAgYWRkX3RyYWNlKHRoZXRhPXA5JGZ2JHRoZXRhX3VuY3V0X3oqMTgwL3BpLCByPXA5JGZ2JGZpdCwgbGluZT1saXN0KGNvbG9yPWNvbG9yc1s5XSwgd2lkdGg9Mi41KSwKICAgICAgICAgICAgbmFtZT1zbW9vdGhfbmFtZXNbOV0pICU+JQogIGFkZF90cmFjZSh0aGV0YT1wMTAkZnYkdGhldGFfdW5jdXRfeioxODAvcGksIHI9cDEwJGZ2JGZpdCwgbGluZT1saXN0KGNvbG9yPWNvbG9yc1sxMF0sIHdpZHRoPTIuNSksCiAgICAgICAgICAgIG5hbWU9c21vb3RoX25hbWVzWzEwXSkgJT4lCiAgYWRkX3RyYWNlKHRoZXRhPXAxMSRmdiR0aGV0YV91bmN1dF96KjE4MC9waSwgcj1wMTEkZnYkZml0LCBsaW5lPWxpc3QoY29sb3I9Y29sb3JzWzExXSwgd2lkdGg9Mi41KSwKICAgICAgICAgICAgbmFtZT1zbW9vdGhfbmFtZXNbMTFdKSAlPiUKICBhZGRfdHJhY2UodGhldGE9cDEyJGZ2JHRoZXRhX3VuY3V0X3oqMTgwL3BpLCByPXAxMiRmdiRmaXQsIGxpbmU9bGlzdChjb2xvcj1jb2xvcnNbMTJdLCBkYXNoPSJkYXNoIiwgd2lkdGg9Mi41KSwgbmFtZT1zbW9vdGhfbmFtZXNbMTJdKSAlPiUKICBhZGRfdHJhY2UodGhldGE9cDEzJGZ2JHRoZXRhX3VuY3V0X3oqMTgwL3BpLCByPXAxMyRmdiRmaXQsIGxpbmU9bGlzdChjb2xvcj1jb2xvcnNbMTNdLCB3aWR0aD0yLjUpLAogICAgICAgICAgICBuYW1lPXNtb290aF9uYW1lc1sxM10pICU+JQogIGxheW91dChwb2xhcj1saXN0KHNlY3Rvcj1jKDIwLDE2MCksIHJhZGlhbGF4aXM9bGlzdChhbmdsZT05MCwgcmFuZ2U9YygwLG1heGltdW0pKSwKICAgICAgICAgICAgICAgICAgICBhbmd1bGFyYXhpcz1saXN0KHRoZXRhdW5pdD0ncmFkaWFucycsIGRpcmVjdGlvbj0iY2xvY2t3aXNlIiwgcm90YXRpb249MCkpLAogICAgICAgICB0aXRsZT0iQWxsIHZvd2VscyBwcm9kdWNlZCBieSBOWkUgc3BlYWtlcnMiLAogICAgICAgICBsZWdlbmQ9bGlzdChvcmllbnRhdGlvbj0iaCIsIHhhbmNob3I9ImNlbnRlciIsIHg9MC41LHk9MC4wMDgpKQpwbG90MgppZihwcmludFBERj09VFJVRSkKewogIG9yY2EocGxvdDIsICJGaWd1cmU3KGEpLnBkZiIsZm9ybWF0PSJwZGYiKQogIG9yY2EocGxvdDIsICJGaWd1cmU3KGEpLmpwZyIsZm9ybWF0PSJqcGVnIikKfQoKcm0ocDEscDIscDMscDQscDUscDYscDcscDgscDkscDEwLHAxMSxwMTIscDEzKQpgYGAKCiMjIyBBbGwgTlpFIG5vdGVzCgpgYGB7ciB3YXJuaW5nPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCBlcnJvcj1GQUxTRSwgZmlnLndpZHRoPTgsIGZpZy5oZWlnaHQ9NX0KIyBjb3JyZWN0IG9yZGVyCmNvbG9ycyA9IGMoYmxhY2ssIGJsYWNrLCBibGFjaywgYmxhY2ssIGJsYWNrKQoKcDE9cGxvdF9zbW9vdGgoeD1OWkUuZ2FtLkFSLk1vZDIsIHZpZXc9InRoZXRhX3VuY3V0X3oiLCBjb25kPWxpc3QodG9rZW5Qb29sZWQub3JkPSJCYjIiKSwgcm0ucmFuZWY9VFJVRSkKcDI9cGxvdF9zbW9vdGgoeD1OWkUuZ2FtLkFSLk1vZDIsIHZpZXc9InRoZXRhX3VuY3V0X3oiLCBjb25kPWxpc3QodG9rZW5Qb29sZWQub3JkPSJGMyIpLCBybS5yYW5lZj1UUlVFKQpwMz1wbG90X3Ntb290aCh4PU5aRS5nYW0uQVIuTW9kMiwgdmlldz0idGhldGFfdW5jdXRfeiIsIGNvbmQ9bGlzdCh0b2tlblBvb2xlZC5vcmQ9IkJiMyIpLCBybS5yYW5lZj1UUlVFKQpwND1wbG90X3Ntb290aCh4PU5aRS5nYW0uQVIuTW9kMiwgdmlldz0idGhldGFfdW5jdXRfeiIsIGNvbmQ9bGlzdCh0b2tlblBvb2xlZC5vcmQ9IkQ0IiksIHJtLnJhbmVmPVRSVUUpCnA1PXBsb3Rfc21vb3RoKHg9TlpFLmdhbS5BUi5Nb2QyLCB2aWV3PSJ0aGV0YV91bmN1dF96IiwgY29uZD1saXN0KHRva2VuUG9vbGVkLm9yZD0iRjQiKSwgcm0ucmFuZWY9VFJVRSkKCnNtb290aF9uYW1lcz1jKCJCYjIiLCJGMyIsIkJiMyIsIkQ0IiwiRjQiKQoKIyBzZXQgUmhvIG1heCB0byB0aGUgbWF4IG9mIHRoZSBmaXQgKyA1CiNtYXhfZml0ID0gbWF4KHAxJGZ2JGZpdCwgcDIkZnYkZml0LCBwMyRmdiRmaXQsIHA0JGZ2JGZpdCwgcDUkZnYkZml0KQojbWF4aW11bT1tYXhfZml0KzUKI3JtKG1heF9maXQpCgojIHBsb3QgaW4gcG9sYXIgY29vcmRpbmF0ZXMgd2l0aG91dCBjb25maWRlbmNlIGJvdW5kcwpwPXBsb3RfbHkodHlwZT0nc2NhdHRlcnBvbGFyJywgbW9kZT0nbGluZXMnKSAlPiUKICBhZGRfdHJhY2UodGhldGE9cDEkZnYkdGhldGFfdW5jdXRfeioxODAvcGksIHI9cDEkZnYkZml0LCBsaW5lPWxpc3QoY29sb3I9Y29sb3JzWzFdLCB3aWR0aD0yLjUpLCBuYW1lPXNtb290aF9uYW1lc1sxXSkgJT4lCiAgYWRkX3RyYWNlKHRoZXRhPXAyJGZ2JHRoZXRhX3VuY3V0X3oqMTgwL3BpLCByPXAyJGZ2JGZpdCwgbGluZT1saXN0KGNvbG9yPWNvbG9yc1syXSwgZGFzaD0iZGFzaCIsIHdpZHRoPTIuNSksIG5hbWU9c21vb3RoX25hbWVzWzJdKSAlPiUKICBhZGRfdHJhY2UodGhldGE9cDMkZnYkdGhldGFfdW5jdXRfeioxODAvcGksIHI9cDMkZnYkZml0LCBsaW5lPWxpc3QoY29sb3I9Y29sb3JzWzNdLCBkYXNoPSJkb3QiLCB3aWR0aD0yLjUpLCBuYW1lPXNtb290aF9uYW1lc1szXSkgJT4lCiAgYWRkX3RyYWNlKHRoZXRhPXA0JGZ2JHRoZXRhX3VuY3V0X3oqMTgwL3BpLCByPXA0JGZ2JGZpdCwgbGluZT1saXN0KGNvbG9yPWNvbG9yc1s0XSwgZGFzaD0iZGFzaGRvdCIsIHdpZHRoPTIuNSksIG5hbWU9c21vb3RoX25hbWVzWzRdKSAlPiUKICBhZGRfdHJhY2UodGhldGE9cDUkZnYkdGhldGFfdW5jdXRfeioxODAvcGksIHI9cDUkZnYkZml0LCBsaW5lPWxpc3QoY29sb3I9Y29sb3JzWzVdLCB3aWR0aD0xKSwKICAgICAgICAgICAgbmFtZT1zbW9vdGhfbmFtZXNbNV0pICU+JQogIGxheW91dChwb2xhcj1saXN0KHNlY3Rvcj1jKDIwLDE2MCksIHJhZGlhbGF4aXM9bGlzdChhbmdsZT05MCwgcmFuZ2U9YygwLG1heGltdW0pKSwKICAgICAgICAgICAgICAgICAgICBhbmd1bGFyYXhpcz1saXN0KHRoZXRhdW5pdD0ncmFkaWFucycsIGRpcmVjdGlvbj0iY2xvY2t3aXNlIiwgcm90YXRpb249MCkpLAogICAgICAgICB0aXRsZT0iQWxsIG5vdGVzIHByb2R1Y2VkIGJ5IE5aRSBzcGVha2VycyIsCiAgICAgICAgIGxlZ2VuZD1saXN0KG9yaWVudGF0aW9uPSJoIiwgeGFuY2hvcj0iY2VudGVyIiwgeD0wLjUseT0wLjAxMikpCnAKCmlmKHByaW50UERGPT1UUlVFKQp7CiAgb3JjYShwLCAiRmlndXJlNyhiKS5wZGYiLGZvcm1hdD0icGRmIikKICBvcmNhKHAsICJGaWd1cmU3KGIpLmpwZyIsZm9ybWF0PSJqcGVnIikKfQoKcm0ocDEscDIscDMscDQscDUpCmBgYAoKCiMjIEZpZ3VyZSA4IC0+IEgyIHZvd2VscyBhbmQgbm90ZXMgVG9uZ2FuCgojIyMgQWxsIFRvbmdhbiB2b3dlbHMKCmBgYHtyIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIGVycm9yPUZBTFNFLCBmaWcud2lkdGg9OCwgZmlnLmhlaWdodD01fQojIHVzZSBjb2xvcnMgZnJvbSBQaEQgdGhlc2lzIChsb2FkZWQgYWJvdmUpCmNvbG9ycyA9IGMoT1JBTkdFMCwgZGFya19ibHVlLCBSRUQwLCBwaW5rLCBHUkVFTjApCgojIHJ1biBwbG90X3Ntb290aCB0byBncmFiIHZhbHVlcyBmb3IgZml0LCB1cHBlciAmIGxvd2VyIGJvdW5kcwpwMT1wbG90X3Ntb290aCh4PVRvbmdhbi5nYW0uQVIuTW9kMiwgdmlldz0idGhldGFfdW5jdXRfeiIsIGNvbmQ9bGlzdCh0b2tlblBvb2xlZC5vcmQ9ImkiKSwgcm0ucmFuZWY9VFJVRSkKcDI9cGxvdF9zbW9vdGgoeD1Ub25nYW4uZ2FtLkFSLk1vZDIsIHZpZXc9InRoZXRhX3VuY3V0X3oiLCBjb25kPWxpc3QodG9rZW5Qb29sZWQub3JkPSJlIiksIHJtLnJhbmVmPVRSVUUpCnAzPXBsb3Rfc21vb3RoKHg9VG9uZ2FuLmdhbS5BUi5Nb2QyLCB2aWV3PSJ0aGV0YV91bmN1dF96IiwgY29uZD1saXN0KHRva2VuUG9vbGVkLm9yZD0iYSIpLCBybS5yYW5lZj1UUlVFKQpwND1wbG90X3Ntb290aCh4PVRvbmdhbi5nYW0uQVIuTW9kMiwgdmlldz0idGhldGFfdW5jdXRfeiIsIGNvbmQ9bGlzdCh0b2tlblBvb2xlZC5vcmQ9Im8iKSwgcm0ucmFuZWY9VFJVRSkKcDU9cGxvdF9zbW9vdGgoeD1Ub25nYW4uZ2FtLkFSLk1vZDIsIHZpZXc9InRoZXRhX3VuY3V0X3oiLCBjb25kPWxpc3QodG9rZW5Qb29sZWQub3JkPSJ1IiksIHJtLnJhbmVmPVRSVUUpCnNtb290aF9uYW1lcz1jKCIvaS8iLCIvZS8iLCIvYS8iLCIvby8iLCIvdS8iKQoKIyBzZXQgUmhvIG1heCB0byB0aGUgbWF4IG9mIHRoZSBmaXQgKyBoYWxmIHRoZSBkaWZmZXJlbmNlIGJldHdlZW4gbWF4IG9mIHRoZSBmaXQgYW5kIHRoZSB1cHBlciBsaW1pdAojIG1heF91bCA9IG1heChwMSRmdiR1bCwgcDIkZnYkdWwsIHAzJGZ2JHVsLCBwNCRmdiR1bCwgcDUkZnYkdWwpCiMgbWF4X2ZpdCA9IG1heChwMSRmdiRmaXQsIHAyJGZ2JGZpdCwgcDMkZnYkZml0LCBwNCRmdiRmaXQsIHA1JGZ2JGZpdCkKIyBtYXhpbXVtID0gbWF4X2ZpdCsoKG1heF91bC1tYXhfZml0KS8yKQojIHJtKG1heF91bCwgbWF4X2ZpdCkKbWF4aW11bSA9IG1heChwMSRmdiR1bCwgcDIkZnYkdWwsIHAzJGZ2JHVsLCBwNCRmdiR1bCwgcDUkZnYkdWwpCgojIHBsb3QgaW4gcG9sYXIgY29vcmRpbmF0ZXMgd2l0aCBjb25maWRlbmNlIGJvdW5kcwpwbG90MT1wbG90X2x5KHR5cGU9J3NjYXR0ZXJwb2xhcicsIG1vZGU9J2xpbmVzJykgJT4lIAogIGFkZF90cmFjZSh0aGV0YT1wMSRmdiR0aGV0YV91bmN1dF96KjE4MC9waSwgcj1wMSRmdiRmaXQsIGxpbmU9bGlzdChjb2xvcj1jb2xvcnNbMV0sIHdpZHRoPTIuNSksCiAgICAgICAgICAgIG5hbWU9c21vb3RoX25hbWVzWzFdKSAlPiUgCiAgYWRkX3RyYWNlKHRoZXRhPXAxJGZ2JHRoZXRhX3VuY3V0X3oqMTgwL3BpLCByPXAxJGZ2JHVsLCBsaW5lPWxpc3QoY29sb3I9Y29sb3JzWzFdLCBkYXNoPSJkb3QiLCB3aWR0aD0wLjUpLCBzaG93bGVnZW5kPUZBTFNFKSAlPiUgCiAgYWRkX3RyYWNlKHRoZXRhPXAxJGZ2JHRoZXRhX3VuY3V0X3oqMTgwL3BpLCByPXAxJGZ2JGxsLCBsaW5lPWxpc3QoY29sb3I9Y29sb3JzWzFdLCBkYXNoPSJkb3QiLCB3aWR0aD0wLjUpLCBzaG93bGVnZW5kPUZBTFNFKSAlPiUgCiAgYWRkX3RyYWNlKHRoZXRhPXAyJGZ2JHRoZXRhX3VuY3V0X3oqMTgwL3BpLCByPXAyJGZ2JGZpdCwgbGluZT1saXN0KGNvbG9yPWNvbG9yc1syXSwgd2lkdGg9Mi41KSwgCiAgICAgICAgICAgIG5hbWU9c21vb3RoX25hbWVzWzJdKSAlPiUgCiAgYWRkX3RyYWNlKHRoZXRhPXAyJGZ2JHRoZXRhX3VuY3V0X3oqMTgwL3BpLCByPXAyJGZ2JHVsLCBsaW5lPWxpc3QoY29sb3I9Y29sb3JzWzJdLCBkYXNoPSJkb3QiLCB3aWR0aD0wLjUpLCBzaG93bGVnZW5kPUZBTFNFKSAlPiUgCiAgYWRkX3RyYWNlKHRoZXRhPXAyJGZ2JHRoZXRhX3VuY3V0X3oqMTgwL3BpLCByPXAyJGZ2JGxsLCBsaW5lPWxpc3QoY29sb3I9Y29sb3JzWzJdLCBkYXNoPSJkb3QiLCB3aWR0aD0wLjUpLCBzaG93bGVnZW5kPUZBTFNFKSAlPiUKICBhZGRfdHJhY2UodGhldGE9cDMkZnYkdGhldGFfdW5jdXRfeioxODAvcGksIHI9cDMkZnYkZml0LCBsaW5lPWxpc3QoY29sb3I9Y29sb3JzWzNdLCB3aWR0aD0yLjUpLCAKICAgICAgICAgICAgbmFtZT1zbW9vdGhfbmFtZXNbM10pICU+JSAKICBhZGRfdHJhY2UodGhldGE9cDMkZnYkdGhldGFfdW5jdXRfeioxODAvcGksIHI9cDMkZnYkdWwsIGxpbmU9bGlzdChjb2xvcj1jb2xvcnNbM10sIGRhc2g9ImRvdCIsIHdpZHRoPTAuNSksIHNob3dsZWdlbmQ9RkFMU0UpICU+JSAKICBhZGRfdHJhY2UodGhldGE9cDMkZnYkdGhldGFfdW5jdXRfeioxODAvcGksIHI9cDMkZnYkbGwsIGxpbmU9bGlzdChjb2xvcj1jb2xvcnNbM10sIGRhc2g9ImRvdCIsIHdpZHRoPTAuNSksIHNob3dsZWdlbmQ9RkFMU0UpICU+JQogIGFkZF90cmFjZSh0aGV0YT1wNCRmdiR0aGV0YV91bmN1dF96KjE4MC9waSwgcj1wNCRmdiRmaXQsIGxpbmU9bGlzdChjb2xvcj1jb2xvcnNbNF0sIHdpZHRoPTIuNSksIAogICAgICAgICAgICBuYW1lPXNtb290aF9uYW1lc1s0XSkgJT4lIAogIGFkZF90cmFjZSh0aGV0YT1wNCRmdiR0aGV0YV91bmN1dF96KjE4MC9waSwgcj1wNCRmdiR1bCwgbGluZT1saXN0KGNvbG9yPWNvbG9yc1s0XSwgZGFzaD0iZG90Iiwgd2lkdGg9MC41KSwgc2hvd2xlZ2VuZD1GQUxTRSkgJT4lIAogIGFkZF90cmFjZSh0aGV0YT1wNCRmdiR0aGV0YV91bmN1dF96KjE4MC9waSwgcj1wNCRmdiRsbCwgbGluZT1saXN0KGNvbG9yPWNvbG9yc1s0XSwgZGFzaD0iZG90Iiwgd2lkdGg9MC41KSwgc2hvd2xlZ2VuZD1GQUxTRSkgJT4lCiAgYWRkX3RyYWNlKHRoZXRhPXA1JGZ2JHRoZXRhX3VuY3V0X3oqMTgwL3BpLCByPXA1JGZ2JGZpdCwgbGluZT1saXN0KGNvbG9yPWNvbG9yc1s1XSwgd2lkdGg9Mi41KSwgCiAgICAgICAgICAgIG5hbWU9c21vb3RoX25hbWVzWzVdKSAlPiUgCiAgYWRkX3RyYWNlKHRoZXRhPXA1JGZ2JHRoZXRhX3VuY3V0X3oqMTgwL3BpLCByPXA1JGZ2JHVsLCBsaW5lPWxpc3QoY29sb3I9Y29sb3JzWzVdLCBkYXNoPSJkb3QiLCB3aWR0aD0wLjUpLCBzaG93bGVnZW5kPUZBTFNFKSAlPiUgCiAgYWRkX3RyYWNlKHRoZXRhPXA1JGZ2JHRoZXRhX3VuY3V0X3oqMTgwL3BpLCByPXA1JGZ2JGxsLCBsaW5lPWxpc3QoY29sb3I9Y29sb3JzWzVdLCBkYXNoPSJkb3QiLCB3aWR0aD0wLjUpLCBzaG93bGVnZW5kPUZBTFNFKSAlPiUKICBsYXlvdXQocG9sYXI9bGlzdChzZWN0b3I9YygyMCwxNjApLCByYWRpYWxheGlzPWxpc3QoYW5nbGU9OTAsIHJhbmdlPWMoMCxtYXhpbXVtKSksCiAgICAgICAgICAgICAgICAgICAgYW5ndWxhcmF4aXM9bGlzdCh0aGV0YXVuaXQ9J3JhZGlhbnMnLCBkaXJlY3Rpb249ImNsb2Nrd2lzZSIsIHJvdGF0aW9uPTApKSwgCiAgICAgICAgIHRpdGxlPSJBbGwgdm93ZWxzIHByb2R1Y2VkIGJ5IFRvbmdhbiBzcGVha2VycyIsCiAgICAgICAgIGxlZ2VuZD1saXN0KG9yaWVudGF0aW9uPSJoIiwgeGFuY2hvcj0iY2VudGVyIiwgeD0wLjUseT0wLjAxMikpCnBsb3QxCgojICMgc2V0IFJobyBtYXggdG8gdGhlIG1heCBvZiB0aGUgZml0ICsgNQojIG1heF9maXQgPSBtYXgocDEkZnYkZml0LCBwMiRmdiRmaXQsIHAzJGZ2JGZpdCwgcDQkZnYkZml0LCBwNSRmdiRmaXQpCiMgbWF4aW11bT1tYXhfZml0KzUKIyBybShtYXhfZml0KQojIAojICMgcGxvdCBpbiBwb2xhciBjb29yZGluYXRlcyB3aXRoIGNvbmZpZGVuY2UgYm91bmRzCiMgcGxvdDI9cGxvdF9seSh0eXBlPSdzY2F0dGVycG9sYXInLCBtb2RlPSdsaW5lcycpICU+JSAKIyAgIGFkZF90cmFjZSh0aGV0YT1wMSRmdiR0aGV0YV91bmN1dF96KjE4MC9waSwgcj1wMSRmdiRmaXQsIGxpbmU9bGlzdChjb2xvcj1jb2xvcnNbMV0sIHdpZHRoPTIuNSksCiMgICAgICAgICAgICAgbmFtZT1zbW9vdGhfbmFtZXNbMV0pICU+JSAKIyAgIGFkZF90cmFjZSh0aGV0YT1wMiRmdiR0aGV0YV91bmN1dF96KjE4MC9waSwgcj1wMiRmdiRmaXQsIGxpbmU9bGlzdChjb2xvcj1jb2xvcnNbMl0sIHdpZHRoPTIuNSksIAojICAgICAgICAgICAgIG5hbWU9c21vb3RoX25hbWVzWzJdKSAlPiUgCiMgICBhZGRfdHJhY2UodGhldGE9cDMkZnYkdGhldGFfdW5jdXRfeioxODAvcGksIHI9cDMkZnYkZml0LCBsaW5lPWxpc3QoY29sb3I9Y29sb3JzWzNdLCB3aWR0aD0yLjUpLCAKIyAgICAgICAgICAgICBuYW1lPXNtb290aF9uYW1lc1szXSkgJT4lIAojICAgYWRkX3RyYWNlKHRoZXRhPXA0JGZ2JHRoZXRhX3VuY3V0X3oqMTgwL3BpLCByPXA0JGZ2JGZpdCwgbGluZT1saXN0KGNvbG9yPWNvbG9yc1s0XSwgd2lkdGg9Mi41KSwgCiMgICAgICAgICAgICAgbmFtZT1zbW9vdGhfbmFtZXNbNF0pICU+JSAKIyAgIGFkZF90cmFjZSh0aGV0YT1wNSRmdiR0aGV0YV91bmN1dF96KjE4MC9waSwgcj1wNSRmdiRmaXQsIGxpbmU9bGlzdChjb2xvcj1jb2xvcnNbNV0sIHdpZHRoPTIuNSksIAojICAgICAgICAgICAgIG5hbWU9c21vb3RoX25hbWVzWzVdKSAlPiUgCiMgICBsYXlvdXQocG9sYXI9bGlzdChzZWN0b3I9YygyMCwxNjApLCByYWRpYWxheGlzPWxpc3QoYW5nbGU9OTAsIHJhbmdlPWMoMCxtYXhpbXVtKSksCiMgICAgICAgICAgICAgICAgICAgICBhbmd1bGFyYXhpcz1saXN0KHRoZXRhdW5pdD0ncmFkaWFucycsIGRpcmVjdGlvbj0iY2xvY2t3aXNlIiwgcm90YXRpb249MCkpLCAKIyAgICAgICAgICB0aXRsZT0iQWxsIHZvd2VscyBwcm9kdWNlZCBieSBUb25nYW4gc3BlYWtlcnMiLAojICAgICAgICAgIGxlZ2VuZD1saXN0KG9yaWVudGF0aW9uPSJoIiwgeGFuY2hvcj0iY2VudGVyIiwgeD0wLjUpKQojIHBsb3QyCmlmKHByaW50UERGPT1UUlVFKQp7CgogIG9yY2EocGxvdDEsICJGaWd1cmU4KGEpLnBkZiIsZm9ybWF0PSJwZGYiKQogIG9yY2EocGxvdDEsICJGaWd1cmU4KGEpLmpwZyIsZm9ybWF0PSJqcGVnIikKfQogIApybShwMSxwMixwMyxwNCxwNSkKYGBgCgojIyMgQWxsIFRvbmdhbiBub3RlcwoKYGBge3Igd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgZXJyb3I9RkFMU0UsIGZpZy53aWR0aD04LCBmaWcuaGVpZ2h0PTV9CiMgdXNlIGNvbG9ycyBmcm9tIFBoRCB0aGVzaXMgKGxvYWRlZCBhYm92ZSkKY29sb3JzID0gYyhibGFjaywgYmxhY2ssIGJsYWNrLCBibGFjaywgYmxhY2spCgpwMT1wbG90X3Ntb290aCh4PVRvbmdhbi5nYW0uQVIuTW9kMiwgdmlldz0idGhldGFfdW5jdXRfeiIsIGNvbmQ9bGlzdCh0b2tlblBvb2xlZC5vcmQ9IkJiMiIpLCBybS5yYW5lZj1UUlVFKQpwMj1wbG90X3Ntb290aCh4PVRvbmdhbi5nYW0uQVIuTW9kMiwgdmlldz0idGhldGFfdW5jdXRfeiIsIGNvbmQ9bGlzdCh0b2tlblBvb2xlZC5vcmQ9IkYzIiksIHJtLnJhbmVmPVRSVUUpCnAzPXBsb3Rfc21vb3RoKHg9VG9uZ2FuLmdhbS5BUi5Nb2QyLCB2aWV3PSJ0aGV0YV91bmN1dF96IiwgY29uZD1saXN0KHRva2VuUG9vbGVkLm9yZD0iQmIzIiksIHJtLnJhbmVmPVRSVUUpCnA0PXBsb3Rfc21vb3RoKHg9VG9uZ2FuLmdhbS5BUi5Nb2QyLCB2aWV3PSJ0aGV0YV91bmN1dF96IiwgY29uZD1saXN0KHRva2VuUG9vbGVkLm9yZD0iRDQiKSwgcm0ucmFuZWY9VFJVRSkKcDU9cGxvdF9zbW9vdGgoeD1Ub25nYW4uZ2FtLkFSLk1vZDIsIHZpZXc9InRoZXRhX3VuY3V0X3oiLCBjb25kPWxpc3QodG9rZW5Qb29sZWQub3JkPSJGNCIpLCBybS5yYW5lZj1UUlVFKQoKc21vb3RoX25hbWVzPWMoIkJiMiIsIkYzIiwiQmIzIiwiRDQiLCJGNCIpCgojIHBsb3QgaW4gcG9sYXIgY29vcmRpbmF0ZXMgd2l0aG91dCBjb25maWRlbmNlIGJvdW5kcwpwPXBsb3RfbHkodHlwZT0nc2NhdHRlcnBvbGFyJywgbW9kZT0nbGluZXMnKSAlPiUgCiAgYWRkX3RyYWNlKHRoZXRhPXAxJGZ2JHRoZXRhX3VuY3V0X3oqMTgwL3BpLCByPXAxJGZ2JGZpdCwgbGluZT1saXN0KGNvbG9yPWNvbG9yc1sxXSwgd2lkdGg9Mi41KSwgbmFtZT1zbW9vdGhfbmFtZXNbMV0pICU+JSAKICBhZGRfdHJhY2UodGhldGE9cDIkZnYkdGhldGFfdW5jdXRfeioxODAvcGksIHI9cDIkZnYkZml0LCBsaW5lPWxpc3QoY29sb3I9Y29sb3JzWzJdLCBkYXNoPSJkYXNoIiwgd2lkdGg9Mi41KSwgbmFtZT1zbW9vdGhfbmFtZXNbMl0pICU+JSAKICBhZGRfdHJhY2UodGhldGE9cDMkZnYkdGhldGFfdW5jdXRfeioxODAvcGksIHI9cDMkZnYkZml0LCBsaW5lPWxpc3QoY29sb3I9Y29sb3JzWzNdLCBkYXNoPSJkb3QiLCB3aWR0aD0yLjUpLCBuYW1lPXNtb290aF9uYW1lc1szXSkgJT4lIAogIGFkZF90cmFjZSh0aGV0YT1wNCRmdiR0aGV0YV91bmN1dF96KjE4MC9waSwgcj1wNCRmdiRmaXQsIGxpbmU9bGlzdChjb2xvcj1jb2xvcnNbNF0sIGRhc2g9ImRhc2hkb3QiLCB3aWR0aD0yLjUpLCBuYW1lPXNtb290aF9uYW1lc1s0XSkgJT4lIAogIGFkZF90cmFjZSh0aGV0YT1wNSRmdiR0aGV0YV91bmN1dF96KjE4MC9waSwgcj1wNSRmdiRmaXQsIGxpbmU9bGlzdChjb2xvcj1jb2xvcnNbNV0sIHdpZHRoPTEpLCAKICAgICAgICAgICAgbmFtZT1zbW9vdGhfbmFtZXNbNV0pICU+JSAKICBsYXlvdXQocG9sYXI9bGlzdChzZWN0b3I9YygyMCwxNjApLCByYWRpYWxheGlzPWxpc3QoYW5nbGU9OTAsIHJhbmdlPWMoMCxtYXhpbXVtKSksCiAgICAgICAgICAgICAgICAgICAgYW5ndWxhcmF4aXM9bGlzdCh0aGV0YXVuaXQ9J3JhZGlhbnMnLCBkaXJlY3Rpb249ImNsb2Nrd2lzZSIsIHJvdGF0aW9uPTApKSwgCiAgICAgICAgIHRpdGxlPSJBbGwgbm90ZXMgcHJvZHVjZWQgYnkgVG9uZ2FuIHNwZWFrZXJzIiwKICAgICAgICAgbGVnZW5kPWxpc3Qob3JpZW50YXRpb249ImgiLCB4YW5jaG9yPSJjZW50ZXIiLCB4PTAuNSx5PTAuMDEyKSkKcAoKaWYocHJpbnRQREY9PVRSVUUpCnsKICBvcmNhKHAsICJGaWd1cmU4KGIpLnBkZiIsZm9ybWF0PSJwZGYiKQogIG9yY2EocCwgIkZpZ3VyZTgoYikuanBnIixmb3JtYXQ9ImpwZWciKQp9CiAgCnJtKHAxLHAyLHAzLHA0LHA1KQpgYGAKCgojIyBGaWd1cmUgOSAtPiBIMiBzZWxlY3RlZCB2b3dlbHMgd2l0aCBub3RlcwoKIyMjIHdpdGggTlpFIG5vdGVzCgpgYGB7ciB3YXJuaW5nPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCBlcnJvcj1GQUxTRSwgZmlnLndpZHRoPTgsIGZpZy5oZWlnaHQ9NX0KY29sb3JzID0gYyhibGFjaywgYmxhY2ssIGJsYWNrLCBibGFjaywgYmxhY2ssQlJPV04wLCBHUkFZMCwgUFVSUExFMCwgcGluaywgR1JFRU4wKQoKIyBydW4gcGxvdF9zbW9vdGggdG8gZ3JhYiB2YWx1ZXMgZm9yIGZpdCwgdXBwZXIgJiBsb3dlciBib3VuZHMKIyBOWkUgbm90ZXMKcDE9cGxvdF9zbW9vdGgoeD1OWkUuZ2FtLkFSLk1vZDIsIHZpZXc9InRoZXRhX3VuY3V0X3oiLCBjb25kPWxpc3QodG9rZW5Qb29sZWQub3JkPSJCYjIiKSwgcm0ucmFuZWY9VFJVRSkKcDI9cGxvdF9zbW9vdGgoeD1OWkUuZ2FtLkFSLk1vZDIsIHZpZXc9InRoZXRhX3VuY3V0X3oiLCBjb25kPWxpc3QodG9rZW5Qb29sZWQub3JkPSJGMyIpLCBybS5yYW5lZj1UUlVFKQpwMz1wbG90X3Ntb290aCh4PU5aRS5nYW0uQVIuTW9kMiwgdmlldz0idGhldGFfdW5jdXRfeiIsIGNvbmQ9bGlzdCh0b2tlblBvb2xlZC5vcmQ9IkJiMyIpLCBybS5yYW5lZj1UUlVFKQpwND1wbG90X3Ntb290aCh4PU5aRS5nYW0uQVIuTW9kMiwgdmlldz0idGhldGFfdW5jdXRfeiIsIGNvbmQ9bGlzdCh0b2tlblBvb2xlZC5vcmQ9IkQ0IiksIHJtLnJhbmVmPVRSVUUpCnA1PXBsb3Rfc21vb3RoKHg9TlpFLmdhbS5BUi5Nb2QyLCB2aWV3PSJ0aGV0YV91bmN1dF96IiwgY29uZD1saXN0KHRva2VuUG9vbGVkLm9yZD0iRjQiKSwgcm0ucmFuZWY9VFJVRSkKCiMgdm93ZWxzCnA2PXBsb3Rfc21vb3RoKHg9TlpFLmdhbS5BUi5Nb2QyLCB2aWV3PSJ0aGV0YV91bmN1dF96IiwgY29uZD1saXN0KHRva2VuUG9vbGVkLm9yZD0iyZkiKSwgcm0ucmFuZWY9VFJVRSkKcDc9cGxvdF9zbW9vdGgoeD1OWkUuZ2FtLkFSLk1vZDIsIHZpZXc9InRoZXRhX3VuY3V0X3oiLCBjb25kPWxpc3QodG9rZW5Qb29sZWQub3JkPSLJmSMiKSwgcm0ucmFuZWY9VFJVRSkKcDg9cGxvdF9zbW9vdGgoeD1OWkUuZ2FtLkFSLk1vZDIsIHZpZXc9InRoZXRhX3VuY3V0X3oiLCBjb25kPWxpc3QodG9rZW5Qb29sZWQub3JkPSLJkiIpLCBybS5yYW5lZj1UUlVFKQpwOT1wbG90X3Ntb290aCh4PVRvbmdhbi5nYW0uQVIuTW9kMiwgdmlldz0idGhldGFfdW5jdXRfeiIsIGNvbmQ9bGlzdCh0b2tlblBvb2xlZC5vcmQ9Im8iKSwgcm0ucmFuZWY9VFJVRSkKcDEwPXBsb3Rfc21vb3RoKHg9VG9uZ2FuLmdhbS5BUi5Nb2QyLCB2aWV3PSJ0aGV0YV91bmN1dF96IiwgY29uZD1saXN0KHRva2VuUG9vbGVkLm9yZD0idSIpLCBybS5yYW5lZj1UUlVFKQoKc21vb3RoX25hbWVzPWMoIkJiMiBOWkUiLCJGMyBOWkUiLCJCYjMgTlpFIiwiRDQgTlpFIiwiRjQgTlpFIiwibm9uLWZpbmFsIHNjaHdhIC/JmS8gTlpFIiwiZmluYWwgc2Nod2EgL8mZIy8gTlpFIiwiTE9UIC/Jki8gTlpFIiwiL28vIFRvbmdhbiIsIi91LyBUb25nYW4iKQoKIyBzZXQgUmhvIG1heCB0byB0aGUgbWF4IG9mIHRoZSBmaXQgKyA1Cm1heF9maXQgPSBtYXgocDEkZnYkZml0LCBwMiRmdiRmaXQsIHAzJGZ2JGZpdCwgcDQkZnYkZml0LCBwNSRmdiRmaXQsIHA2JGZ2JGZpdCwgcDckZnYkZml0LCBwOCRmdiRmaXQsIHA5JGZ2JGZpdCwgcDEwJGZ2JGZpdCkKbWF4aW11bT1tYXhfZml0KzUKcm0obWF4X2ZpdCkKCiMgcGxvdCBpbiBwb2xhciBjb29yZGluYXRlcyB3aXRob3V0IGNvbmZpZGVuY2UgYm91bmRzCnBsb3QyPXBsb3RfbHkodHlwZT0nc2NhdHRlcnBvbGFyJywgbW9kZT0nbGluZXMnKSAlPiUKICBhZGRfdHJhY2UodGhldGE9cDEkZnYkdGhldGFfdW5jdXRfeioxODAvcGksIHI9cDEkZnYkZml0LCBsaW5lPWxpc3QoY29sb3I9Y29sb3JzWzFdLCB3aWR0aD0yLjUpLCBuYW1lPXNtb290aF9uYW1lc1sxXSkgJT4lCiAgYWRkX3RyYWNlKHRoZXRhPXAyJGZ2JHRoZXRhX3VuY3V0X3oqMTgwL3BpLCByPXAyJGZ2JGZpdCwgbGluZT1saXN0KGNvbG9yPWNvbG9yc1syXSwgZGFzaD0iZGFzaCIsIHdpZHRoPTIuNSksIG5hbWU9c21vb3RoX25hbWVzWzJdKSAlPiUKICBhZGRfdHJhY2UodGhldGE9cDMkZnYkdGhldGFfdW5jdXRfeioxODAvcGksIHI9cDMkZnYkZml0LCBsaW5lPWxpc3QoY29sb3I9Y29sb3JzWzNdLCBkYXNoPSJkb3QiLCB3aWR0aD0yLjUpLCBuYW1lPXNtb290aF9uYW1lc1szXSkgJT4lCiAgYWRkX3RyYWNlKHRoZXRhPXA0JGZ2JHRoZXRhX3VuY3V0X3oqMTgwL3BpLCByPXA0JGZ2JGZpdCwgbGluZT1saXN0KGNvbG9yPWNvbG9yc1s0XSwgZGFzaD0iZGFzaGRvdCIsIHdpZHRoPTIuNSksIG5hbWU9c21vb3RoX25hbWVzWzRdKSAlPiUKICBhZGRfdHJhY2UodGhldGE9cDUkZnYkdGhldGFfdW5jdXRfeioxODAvcGksIHI9cDUkZnYkZml0LCBsaW5lPWxpc3QoY29sb3I9Y29sb3JzWzVdLCB3aWR0aD0xKSwgbmFtZT1zbW9vdGhfbmFtZXNbNV0pICU+JQogIGFkZF90cmFjZSh0aGV0YT1wNiRmdiR0aGV0YV91bmN1dF96KjE4MC9waSwgcj1wNiRmdiRmaXQsIGxpbmU9bGlzdChjb2xvcj1jb2xvcnNbNl0sIHdpZHRoPTIuNSksIG5hbWU9c21vb3RoX25hbWVzWzZdKSAlPiUKICBhZGRfdHJhY2UodGhldGE9cDckZnYkdGhldGFfdW5jdXRfeioxODAvcGksIHI9cDckZnYkZml0LCBsaW5lPWxpc3QoY29sb3I9Y29sb3JzWzddLCB3aWR0aD0yLjUpLCBuYW1lPXNtb290aF9uYW1lc1s3XSkgJT4lCiAgYWRkX3RyYWNlKHRoZXRhPXA4JGZ2JHRoZXRhX3VuY3V0X3oqMTgwL3BpLCByPXA4JGZ2JGZpdCwgbGluZT1saXN0KGNvbG9yPWNvbG9yc1s4XSwgZGFzaD0iZGFzaCIsIHdpZHRoPTIuNSksIG5hbWU9c21vb3RoX25hbWVzWzhdKSAlPiUKICBhZGRfdHJhY2UodGhldGE9cDkkZnYkdGhldGFfdW5jdXRfeioxODAvcGksIHI9cDkkZnYkZml0LCBsaW5lPWxpc3QoY29sb3I9Y29sb3JzWzldLCB3aWR0aD0yLjUpLCBuYW1lPXNtb290aF9uYW1lc1s5XSkgJT4lCiAgYWRkX3RyYWNlKHRoZXRhPXAxMCRmdiR0aGV0YV91bmN1dF96KjE4MC9waSwgcj1wMTAkZnYkZml0LCBsaW5lPWxpc3QoY29sb3I9Y29sb3JzWzEwXSwgd2lkdGg9Mi41KSwKbmFtZT1zbW9vdGhfbmFtZXNbMTBdKSAlPiUKICBsYXlvdXQocG9sYXI9bGlzdChzZWN0b3I9YygyMCwxNjApLCByYWRpYWxheGlzPWxpc3QoYW5nbGU9OTAsIHJhbmdlPWMoMCxtYXhpbXVtKSksCiAgICAgICAgICAgICAgICAgICAgYW5ndWxhcmF4aXM9bGlzdCh0aGV0YXVuaXQ9J3JhZGlhbnMnLCBkaXJlY3Rpb249ImNsb2Nrd2lzZSIsIHJvdGF0aW9uPTApKSwKICAgICAgICAgdGl0bGU9IlRvbmdhbiAmIE5aRSB2b3dlbHMgY2xvc2VzdCB0byBwbGF5aW5nIHBvc2l0aW9uIHdpdGggTlpFIG5vdGVzIixsZWdlbmQ9bGlzdChvcmllbnRhdGlvbj0iaCIsIHhhbmNob3I9ImNlbnRlciIsIHg9MC41LHk9MC4wMDgpKQpwbG90MgoKaWYocHJpbnRQREY9PVRSVUUpCnsKICBvcmNhKHBsb3QyLCAiRmlndXJlOShhKS5wZGYiLGZvcm1hdD0icGRmIikKICBvcmNhKHBsb3QyLCAiRmlndXJlOShhKS5qcGVnIixmb3JtYXQ9ImpwZWciKQp9CgpybShwMSxwMixwMyxwNCxwNSxwNixwNyxwOCxwOSxwMTApCmBgYAoKIyMjIHdpdGggVG9uZ2FuIG5vdGVzCgpgYGB7ciB3YXJuaW5nPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCBlcnJvcj1GQUxTRSwgZmlnLndpZHRoPTgsIGZpZy5oZWlnaHQ9NX0KY29sb3JzID0gYyhibGFjaywgYmxhY2ssIGJsYWNrLCBibGFjaywgYmxhY2ssQlJPV04wLCBHUkFZMCwgUFVSUExFMCwgcGluaywgR1JFRU4wKQoKIyBydW4gcGxvdF9zbW9vdGggdG8gZ3JhYiB2YWx1ZXMgZm9yIGZpdCwgdXBwZXIgJiBsb3dlciBib3VuZHMKIyBUb25nYW4gbm90ZXMKcDE9cGxvdF9zbW9vdGgoeD1Ub25nYW4uZ2FtLkFSLk1vZDIsIHZpZXc9InRoZXRhX3VuY3V0X3oiLCBjb25kPWxpc3QodG9rZW5Qb29sZWQub3JkPSJCYjIiKSwgcm0ucmFuZWY9VFJVRSkKcDI9cGxvdF9zbW9vdGgoeD1Ub25nYW4uZ2FtLkFSLk1vZDIsIHZpZXc9InRoZXRhX3VuY3V0X3oiLCBjb25kPWxpc3QodG9rZW5Qb29sZWQub3JkPSJGMyIpLCBybS5yYW5lZj1UUlVFKQpwMz1wbG90X3Ntb290aCh4PVRvbmdhbi5nYW0uQVIuTW9kMiwgdmlldz0idGhldGFfdW5jdXRfeiIsIGNvbmQ9bGlzdCh0b2tlblBvb2xlZC5vcmQ9IkJiMyIpLCBybS5yYW5lZj1UUlVFKQpwND1wbG90X3Ntb290aCh4PVRvbmdhbi5nYW0uQVIuTW9kMiwgdmlldz0idGhldGFfdW5jdXRfeiIsIGNvbmQ9bGlzdCh0b2tlblBvb2xlZC5vcmQ9IkQ0IiksIHJtLnJhbmVmPVRSVUUpCnA1PXBsb3Rfc21vb3RoKHg9VG9uZ2FuLmdhbS5BUi5Nb2QyLCB2aWV3PSJ0aGV0YV91bmN1dF96IiwgY29uZD1saXN0KHRva2VuUG9vbGVkLm9yZD0iRjQiKSwgcm0ucmFuZWY9VFJVRSkKCiMgdm93ZWxzCnA2PXBsb3Rfc21vb3RoKHg9TlpFLmdhbS5BUi5Nb2QyLCB2aWV3PSJ0aGV0YV91bmN1dF96IiwgY29uZD1saXN0KHRva2VuUG9vbGVkLm9yZD0iyZkiKSwgcm0ucmFuZWY9VFJVRSkKcDc9cGxvdF9zbW9vdGgoeD1OWkUuZ2FtLkFSLk1vZDIsIHZpZXc9InRoZXRhX3VuY3V0X3oiLCBjb25kPWxpc3QodG9rZW5Qb29sZWQub3JkPSLJmSMiKSwgcm0ucmFuZWY9VFJVRSkKcDg9cGxvdF9zbW9vdGgoeD1OWkUuZ2FtLkFSLk1vZDIsIHZpZXc9InRoZXRhX3VuY3V0X3oiLCBjb25kPWxpc3QodG9rZW5Qb29sZWQub3JkPSLJkiIpLCBybS5yYW5lZj1UUlVFKQpwOT1wbG90X3Ntb290aCh4PVRvbmdhbi5nYW0uQVIuTW9kMiwgdmlldz0idGhldGFfdW5jdXRfeiIsIGNvbmQ9bGlzdCh0b2tlblBvb2xlZC5vcmQ9Im8iKSwgcm0ucmFuZWY9VFJVRSkKcDEwPXBsb3Rfc21vb3RoKHg9VG9uZ2FuLmdhbS5BUi5Nb2QyLCB2aWV3PSJ0aGV0YV91bmN1dF96IiwgY29uZD1saXN0KHRva2VuUG9vbGVkLm9yZD0idSIpLCBybS5yYW5lZj1UUlVFKQoKc21vb3RoX25hbWVzPWMoIkJiMiBUb25nYW4iLCJGMyBUb25nYW4iLCJCYjMgVG9uZ2FuIiwiRDQgVG9uZ2FuIiwiRjQgVG9uZ2FuIiwibm9uLWZpbmFsIHNjaHdhIC/JmS8gTlpFIiwiZmluYWwgc2Nod2EgL8mZIy8gTlpFIiwiTE9UIC/Jki8gTlpFIiwiL28vIFRvbmdhbiIsIi91LyBUb25nYW4iKQoKIyAjIHNldCBSaG8gbWF4IHRvIHRoZSBtYXggb2YgdGhlIGZpdCArIDUKIyBtYXhfZml0ID0gbWF4KHAxJGZ2JGZpdCwgcDIkZnYkZml0LCBwMyRmdiRmaXQsIHA0JGZ2JGZpdCwgcDUkZnYkZml0LCBwNiRmdiRmaXQsIHA3JGZ2JGZpdCwgcDgkZnYkZml0LCBwOSRmdiRmaXQsIHAxMCRmdiRmaXQpCiMgbWF4aW11bT1tYXhfZml0KzUKIyBybShtYXhfZml0KQojIAojICMgcGxvdCBpbiBwb2xhciBjb29yZGluYXRlcyB3aXRoIGNvbmZpZGVuY2UgYm91bmRzCiMgcGxvdDE9cGxvdF9seSh0eXBlPSdzY2F0dGVycG9sYXInLCBtb2RlPSdsaW5lcycpICU+JQojICAgYWRkX3RyYWNlKHRoZXRhPXAxJGZ2JHRoZXRhX3VuY3V0X3oqMTgwL3BpLCByPXAxJGZ2JGZpdCwgbGluZT1saXN0KGNvbG9yPWNvbG9yc1sxXSwgd2lkdGg9Mi41KSwgbmFtZT1zbW9vdGhfbmFtZXNbMV0pICU+JQojICAgYWRkX3RyYWNlKHRoZXRhPXAxJGZ2JHRoZXRhX3VuY3V0X3oqMTgwL3BpLCByPXAxJGZ2JHVsLCBsaW5lPWxpc3QoY29sb3I9Y29sb3JzWzFdLCBkYXNoPSJkb3QiLCB3aWR0aD0wLjUpLCBzaG93bGVnZW5kPUZBTFNFKSAlPiUKIyAgIGFkZF90cmFjZSh0aGV0YT1wMSRmdiR0aGV0YV91bmN1dF96KjE4MC9waSwgcj1wMSRmdiRsbCwgbGluZT1saXN0KGNvbG9yPWNvbG9yc1sxXSwgZGFzaD0iZG90Iiwgd2lkdGg9MC41KSwgc2hvd2xlZ2VuZD1GQUxTRSkgJT4lCiMgICBhZGRfdHJhY2UodGhldGE9cDIkZnYkdGhldGFfdW5jdXRfeioxODAvcGksIHI9cDIkZnYkZml0LCBsaW5lPWxpc3QoY29sb3I9Y29sb3JzWzJdLCB3aWR0aD0yLjUpLCBuYW1lPXNtb290aF9uYW1lc1syXSkgJT4lCiMgICBhZGRfdHJhY2UodGhldGE9cDIkZnYkdGhldGFfdW5jdXRfeioxODAvcGksIHI9cDIkZnYkdWwsIGxpbmU9bGlzdChjb2xvcj1jb2xvcnNbMl0sIGRhc2g9ImRvdCIsIHdpZHRoPTAuNSksIHNob3dsZWdlbmQ9RkFMU0UpICU+JQojICAgYWRkX3RyYWNlKHRoZXRhPXAyJGZ2JHRoZXRhX3VuY3V0X3oqMTgwL3BpLCByPXAyJGZ2JGxsLCBsaW5lPWxpc3QoY29sb3I9Y29sb3JzWzJdLCBkYXNoPSJkb3QiLCB3aWR0aD0wLjUpLCBzaG93bGVnZW5kPUZBTFNFKSAlPiUKIyAgIGFkZF90cmFjZSh0aGV0YT1wMyRmdiR0aGV0YV91bmN1dF96KjE4MC9waSwgcj1wMyRmdiRmaXQsIGxpbmU9bGlzdChjb2xvcj1jb2xvcnNbM10sIGRhc2g9ImRhc2giLCB3aWR0aD0yLjUpLCBuYW1lPXNtb290aF9uYW1lc1szXSkgJT4lCiMgICBhZGRfdHJhY2UodGhldGE9cDMkZnYkdGhldGFfdW5jdXRfeioxODAvcGksIHI9cDMkZnYkdWwsIGxpbmU9bGlzdChjb2xvcj1jb2xvcnNbM10sIGRhc2g9ImRhc2giLCB3aWR0aD0wLjUpLCBzaG93bGVnZW5kPUZBTFNFKSAlPiUKIyAgIGFkZF90cmFjZSh0aGV0YT1wMyRmdiR0aGV0YV91bmN1dF96KjE4MC9waSwgcj1wMyRmdiRsbCwgbGluZT1saXN0KGNvbG9yPWNvbG9yc1szXSwgZGFzaD0iZGFzaCIsIHdpZHRoPTAuNSksIHNob3dsZWdlbmQ9RkFMU0UpICU+JQojICAgYWRkX3RyYWNlKHRoZXRhPXA0JGZ2JHRoZXRhX3VuY3V0X3oqMTgwL3BpLCByPXA0JGZ2JGZpdCwgbGluZT1saXN0KGNvbG9yPWNvbG9yc1s0XSwgd2lkdGg9Mi41KSwKIyAgICAgICAgICAgICBuYW1lPXNtb290aF9uYW1lc1s0XSkgJT4lCiMgICBhZGRfdHJhY2UodGhldGE9cDQkZnYkdGhldGFfdW5jdXRfeioxODAvcGksIHI9cDQkZnYkdWwsIGxpbmU9bGlzdChjb2xvcj1jb2xvcnNbNF0sIGRhc2g9ImRvdCIsIHdpZHRoPTAuNSksIHNob3dsZWdlbmQ9RkFMU0UpICU+JQojICAgYWRkX3RyYWNlKHRoZXRhPXA0JGZ2JHRoZXRhX3VuY3V0X3oqMTgwL3BpLCByPXA0JGZ2JGxsLCBsaW5lPWxpc3QoY29sb3I9Y29sb3JzWzRdLCBkYXNoPSJkb3QiLCB3aWR0aD0wLjUpLCBzaG93bGVnZW5kPUZBTFNFKSAlPiUKIyAgIGFkZF90cmFjZSh0aGV0YT1wNSRmdiR0aGV0YV91bmN1dF96KjE4MC9waSwgcj1wNSRmdiRmaXQsIGxpbmU9bGlzdChjb2xvcj1jb2xvcnNbNV0sIHdpZHRoPTIuNSksCiMgICAgICAgICAgICAgbmFtZT1zbW9vdGhfbmFtZXNbNV0pICU+JQojICAgYWRkX3RyYWNlKHRoZXRhPXA1JGZ2JHRoZXRhX3VuY3V0X3oqMTgwL3BpLCByPXA1JGZ2JHVsLCBsaW5lPWxpc3QoY29sb3I9Y29sb3JzWzVdLCBkYXNoPSJkb3QiLCB3aWR0aD0wLjUpLCBzaG93bGVnZW5kPUZBTFNFKSAlPiUKIyAgIGFkZF90cmFjZSh0aGV0YT1wNSRmdiR0aGV0YV91bmN1dF96KjE4MC9waSwgcj1wNSRmdiRsbCwgbGluZT1saXN0KGNvbG9yPWNvbG9yc1s1XSwgZGFzaD0iZG90Iiwgd2lkdGg9MC41KSwgc2hvd2xlZ2VuZD1GQUxTRSkgJT4lCiMgICBhZGRfdHJhY2UodGhldGE9cDYkZnYkdGhldGFfdW5jdXRfeioxODAvcGksIHI9cDYkZnYkZml0LCBsaW5lPWxpc3QoY29sb3I9Y29sb3JzWzZdLCB3aWR0aD0xKSwKIyAgICAgICAgICAgICBuYW1lPXNtb290aF9uYW1lc1s2XSkgJT4lCiMgICBhZGRfdHJhY2UodGhldGE9cDYkZnYkdGhldGFfdW5jdXRfeioxODAvcGksIHI9cDYkZnYkdWwsIGxpbmU9bGlzdChjb2xvcj1jb2xvcnNbNl0sIGRhc2g9ImRvdCIsIHdpZHRoPTAuNSksIHNob3dsZWdlbmQ9RkFMU0UpICU+JQojICAgYWRkX3RyYWNlKHRoZXRhPXA2JGZ2JHRoZXRhX3VuY3V0X3oqMTgwL3BpLCByPXA2JGZ2JGxsLCBsaW5lPWxpc3QoY29sb3I9Y29sb3JzWzZdLCBkYXNoPSJkb3QiLCB3aWR0aD0wLjUpLCBzaG93bGVnZW5kPUZBTFNFKSAlPiUKIyAgIGFkZF90cmFjZSh0aGV0YT1wNyRmdiR0aGV0YV91bmN1dF96KjE4MC9waSwgcj1wNyRmdiRmaXQsIGxpbmU9bGlzdChjb2xvcj1jb2xvcnNbN10sIGRhc2g9ImRhc2hkb3QiLCB3aWR0aD0yLjUpLCBuYW1lPXNtb290aF9uYW1lc1s3XSkgJT4lCiMgICBhZGRfdHJhY2UodGhldGE9cDckZnYkdGhldGFfdW5jdXRfeioxODAvcGksIHI9cDckZnYkdWwsIGxpbmU9bGlzdChjb2xvcj1jb2xvcnNbN10sIGRhc2g9ImRhc2hkb3QiLCB3aWR0aD0wLjUpLCBzaG93bGVnZW5kPUZBTFNFKSAlPiUKIyAgIGFkZF90cmFjZSh0aGV0YT1wNyRmdiR0aGV0YV91bmN1dF96KjE4MC9waSwgcj1wNyRmdiRsbCwgbGluZT1saXN0KGNvbG9yPWNvbG9yc1s3XSwgZGFzaD0iZGFzaGRvdCIsIHdpZHRoPTAuNSksIHNob3dsZWdlbmQ9RkFMU0UpICU+JQojICAgYWRkX3RyYWNlKHRoZXRhPXA4JGZ2JHRoZXRhX3VuY3V0X3oqMTgwL3BpLCByPXA4JGZ2JGZpdCwgbGluZT1saXN0KGNvbG9yPWNvbG9yc1s4XSwgZGFzaD0iZG90Iiwgd2lkdGg9Mi41KSwgbmFtZT1zbW9vdGhfbmFtZXNbOF0pICU+JQojICAgYWRkX3RyYWNlKHRoZXRhPXA4JGZ2JHRoZXRhX3VuY3V0X3oqMTgwL3BpLCByPXA4JGZ2JHVsLCBsaW5lPWxpc3QoY29sb3I9Y29sb3JzWzhdLCBkYXNoPSJkb3QiLCB3aWR0aD0wLjUpLCBzaG93bGVnZW5kPUZBTFNFKSAlPiUKIyAgIGFkZF90cmFjZSh0aGV0YT1wOCRmdiR0aGV0YV91bmN1dF96KjE4MC9waSwgcj1wOCRmdiRsbCwgbGluZT1saXN0KGNvbG9yPWNvbG9yc1s4XSwgZGFzaD0iZG90Iiwgd2lkdGg9MC41KSwgc2hvd2xlZ2VuZD1GQUxTRSkgJT4lCiMgICBhZGRfdHJhY2UodGhldGE9cDkkZnYkdGhldGFfdW5jdXRfeioxODAvcGksIHI9cDkkZnYkZml0LCBsaW5lPWxpc3QoY29sb3I9Y29sb3JzWzldLCBkYXNoPSJkYXNoIiwgd2lkdGg9Mi41KSwgbmFtZT1zbW9vdGhfbmFtZXNbOV0pICU+JQojICAgYWRkX3RyYWNlKHRoZXRhPXA5JGZ2JHRoZXRhX3VuY3V0X3oqMTgwL3BpLCByPXA5JGZ2JHVsLCBsaW5lPWxpc3QoY29sb3I9Y29sb3JzWzldLCBkYXNoPSJkb3QiLCB3aWR0aD0wLjUpLCBzaG93bGVnZW5kPUZBTFNFKSAlPiUKIyAgIGFkZF90cmFjZSh0aGV0YT1wOSRmdiR0aGV0YV91bmN1dF96KjE4MC9waSwgcj1wOSRmdiRsbCwgbGluZT1saXN0KGNvbG9yPWNvbG9yc1s5XSwgZGFzaD0iZG90Iiwgd2lkdGg9MC41KSwgc2hvd2xlZ2VuZD1GQUxTRSkgJT4lCiMgICBhZGRfdHJhY2UodGhldGE9cDEwJGZ2JHRoZXRhX3VuY3V0X3oqMTgwL3BpLCByPXAxMCRmdiRmaXQsIGxpbmU9bGlzdChjb2xvcj1jb2xvcnNbMTBdLCB3aWR0aD0yLjUpLAojICAgICAgICAgICAgIG5hbWU9c21vb3RoX25hbWVzWzEwXSkgJT4lCiMgICBhZGRfdHJhY2UodGhldGE9cDEwJGZ2JHRoZXRhX3VuY3V0X3oqMTgwL3BpLCByPXAxMCRmdiR1bCwgbGluZT1saXN0KGNvbG9yPWNvbG9yc1sxMF0sIGRhc2g9ImRvdCIsIHdpZHRoPTAuNSksIHNob3dsZWdlbmQ9RkFMU0UpICU+JQojICAgYWRkX3RyYWNlKHRoZXRhPXAxMCRmdiR0aGV0YV91bmN1dF96KjE4MC9waSwgcj1wMTAkZnYkbGwsIGxpbmU9bGlzdChjb2xvcj1jb2xvcnNbMTBdLCBkYXNoPSJkb3QiLCB3aWR0aD0wLjUpLCBzaG93bGVnZW5kPUZBTFNFKSAlPiUKIyAgIGxheW91dChwb2xhcj1saXN0KHNlY3Rvcj1jKDIwLDE2MCksIHJhZGlhbGF4aXM9bGlzdChhbmdsZT05MCwgcmFuZ2U9YygwLG1heGltdW0pKSwKIyAgICAgICAgICAgICAgICAgICAgIGFuZ3VsYXJheGlzPWxpc3QodGhldGF1bml0PSdyYWRpYW5zJywgZGlyZWN0aW9uPSJjbG9ja3dpc2UiLCByb3RhdGlvbj0wKSksCiMgICAgICAgICAgdGl0bGU9IlRvbmdhbiAmIE5aRSB2b3dlbHMgY2xvc2VzdCB0byBwbGF5aW5nIHBvc2l0aW9uIHdpdGggVG9uZ2FuIG5vdGVzIikKIyBwbG90MQoKIyBzZXQgUmhvIG1heCB0byB0aGUgbWF4IG9mIHRoZSBmaXQgKyA1Cm1heF9maXQgPSBtYXgocDEkZnYkZml0LCBwMiRmdiRmaXQsIHAzJGZ2JGZpdCwgcDQkZnYkZml0LCBwNSRmdiRmaXQsIHA2JGZ2JGZpdCwgcDckZnYkZml0LCBwOCRmdiRmaXQsIHA5JGZ2JGZpdCwgcDEwJGZ2JGZpdCkKbWF4aW11bT1tYXhfZml0KzUKcm0obWF4X2ZpdCkKCiMgcGxvdCBpbiBwb2xhciBjb29yZGluYXRlcyB3aXRob3V0IGNvbmZpZGVuY2UgYm91bmRzCnBsb3QyPXBsb3RfbHkodHlwZT0nc2NhdHRlcnBvbGFyJywgbW9kZT0nbGluZXMnKSAlPiUKICBhZGRfdHJhY2UodGhldGE9cDEkZnYkdGhldGFfdW5jdXRfeioxODAvcGksIHI9cDEkZnYkZml0LCBsaW5lPWxpc3QoY29sb3I9Y29sb3JzWzFdLCB3aWR0aD0yLjUpLCBuYW1lPXNtb290aF9uYW1lc1sxXSkgJT4lCiAgYWRkX3RyYWNlKHRoZXRhPXAyJGZ2JHRoZXRhX3VuY3V0X3oqMTgwL3BpLCByPXAyJGZ2JGZpdCwgbGluZT1saXN0KGNvbG9yPWNvbG9yc1syXSwgZGFzaD0iZGFzaCIsIHdpZHRoPTIuNSksIG5hbWU9c21vb3RoX25hbWVzWzJdKSAlPiUKICBhZGRfdHJhY2UodGhldGE9cDMkZnYkdGhldGFfdW5jdXRfeioxODAvcGksIHI9cDMkZnYkZml0LCBsaW5lPWxpc3QoY29sb3I9Y29sb3JzWzNdLCBkYXNoPSJkb3QiLCB3aWR0aD0yLjUpLCBuYW1lPXNtb290aF9uYW1lc1szXSkgJT4lCiAgYWRkX3RyYWNlKHRoZXRhPXA0JGZ2JHRoZXRhX3VuY3V0X3oqMTgwL3BpLCByPXA0JGZ2JGZpdCwgbGluZT1saXN0KGNvbG9yPWNvbG9yc1s0XSwgZGFzaD0iZGFzaGRvdCIsIHdpZHRoPTIuNSksIG5hbWU9c21vb3RoX25hbWVzWzRdKSAlPiUKICBhZGRfdHJhY2UodGhldGE9cDUkZnYkdGhldGFfdW5jdXRfeioxODAvcGksIHI9cDUkZnYkZml0LCBsaW5lPWxpc3QoY29sb3I9Y29sb3JzWzVdLCB3aWR0aD0xKSwgbmFtZT1zbW9vdGhfbmFtZXNbNV0pICU+JQogIGFkZF90cmFjZSh0aGV0YT1wNiRmdiR0aGV0YV91bmN1dF96KjE4MC9waSwgcj1wNiRmdiRmaXQsIGxpbmU9bGlzdChjb2xvcj1jb2xvcnNbNl0sIHdpZHRoPTIuNSksIG5hbWU9c21vb3RoX25hbWVzWzZdKSAlPiUKICBhZGRfdHJhY2UodGhldGE9cDckZnYkdGhldGFfdW5jdXRfeioxODAvcGksIHI9cDckZnYkZml0LCBsaW5lPWxpc3QoY29sb3I9Y29sb3JzWzddLCB3aWR0aD0yLjUpLCBuYW1lPXNtb290aF9uYW1lc1s3XSkgJT4lCiAgYWRkX3RyYWNlKHRoZXRhPXA4JGZ2JHRoZXRhX3VuY3V0X3oqMTgwL3BpLCByPXA4JGZ2JGZpdCwgbGluZT1saXN0KGNvbG9yPWNvbG9yc1s4XSwgZGFzaD0iZGFzaCIsIHdpZHRoPTIuNSksIG5hbWU9c21vb3RoX25hbWVzWzhdKSAlPiUKICBhZGRfdHJhY2UodGhldGE9cDkkZnYkdGhldGFfdW5jdXRfeioxODAvcGksIHI9cDkkZnYkZml0LCBsaW5lPWxpc3QoY29sb3I9Y29sb3JzWzldLCB3aWR0aD0yLjUpLCBuYW1lPXNtb290aF9uYW1lc1s5XSkgJT4lCiAgYWRkX3RyYWNlKHRoZXRhPXAxMCRmdiR0aGV0YV91bmN1dF96KjE4MC9waSwgcj1wMTAkZnYkZml0LCBsaW5lPWxpc3QoY29sb3I9Y29sb3JzWzEwXSwgd2lkdGg9Mi41KSwKbmFtZT1zbW9vdGhfbmFtZXNbMTBdKSAlPiUKICBsYXlvdXQocG9sYXI9bGlzdChzZWN0b3I9YygyMCwxNjApLCByYWRpYWxheGlzPWxpc3QoYW5nbGU9OTAsIHJhbmdlPWMoMCxtYXhpbXVtKSksCiAgICAgICAgICAgICAgICAgICAgYW5ndWxhcmF4aXM9bGlzdCh0aGV0YXVuaXQ9J3JhZGlhbnMnLCBkaXJlY3Rpb249ImNsb2Nrd2lzZSIsIHJvdGF0aW9uPTApKSwKICAgICAgICAgdGl0bGU9IlRvbmdhbiAmIE5aRSB2b3dlbHMgY2xvc2VzdCB0byBwbGF5aW5nIHBvc2l0aW9uIHdpdGggVG9uZ2FuIG5vdGVzIixsZWdlbmQ9bGlzdChvcmllbnRhdGlvbj0iaCIsIHhhbmNob3I9ImNlbnRlciIsIHg9MC41LHk9MC4wMTIpKQpwbG90MgoKaWYocHJpbnRQREY9PVRSVUUpCnsKICBvcmNhKHBsb3QyLCAiRmlndXJlOShiKS5wZGYiLGZvcm1hdD0icGRmIikKICBvcmNhKHBsb3QyLCAiRmlndXJlOShiKS5qcGVnIixmb3JtYXQ9ImpwZWciKQp9CiAgCnJtKHAxLHAyLHAzLHA0LHA1LHA2LHA3LHA4LHA5LHAxMCkKYGBgCgoKIyMgRmlndXJlIDEwICdjYXJkaW5hbCB2b3dlbHMnIC0+IHVwZGF0ZWQgdmVyc2lvbiB1c2luZyBvbmx5IHZvd2VscyBzdXJyb3VuZGVkIGJ5IGNvcm9uYWxzCgpgYGB7ciB3YXJuaW5nPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCBlcnJvcj1GQUxTRSwgZmlnLndpZHRoPTgsIGZpZy5oZWlnaHQ9NX0KIyBjcmVhdGUgZGZOWkUgJiBkZlRvbmdhbiAtPiBkZiBhbHJlYWR5IGxvYWRlZCBhbmQgbWFuaXB1bGF0ZWQgYWJvdmUKZGZOWkUgPC0gc3Vic2V0KGRmLGRmJG5hdGl2ZV9sZz09Ik5aRSIpCmRmTlpFJHRva2VuUG9vbGVkIDwtIGZhY3RvcihkZk5aRSR0b2tlblBvb2xlZCwgbGV2ZWxzID0gYygiyZDLkCIsIsmQIiwiyZsiLCLJtcuQIiwiZSIsImnLkCIsIsqJy5AiLCLKiiIsIm/LkCIsIsmSIiwiyZgiLCLJmSIsIsmZIyIsIkJiMiIsIkYzIiwiQmIzIiwiRDQiLCJGNCIpKQpkZk5aRSRwbGF5aW5nX3Byb2ZpY2llbmN5IDwtIGFzLmZhY3RvcihkZk5aRSRwbGF5aW5nX3Byb2ZpY2llbmN5KQpkZk5aRSRub3RlX2ludGVuc2l0eVtpcy5uYShkZk5aRSRub3RlX2ludGVuc2l0eSldID0gIk5VTEwiCmRmTlpFJHN1YlZvd2VsSW50IDwtIGludGVyYWN0aW9uKGRmTlpFJHN1YmplY3QsIGRmTlpFJHRva2VuUG9vbGVkKQpkZk5aRSRwcmVjU291bmRWb3dlbEludCA8LSBpbnRlcmFjdGlvbihkZk5aRSRzcGVlY2hfcHJlY19wb29sZWQsIGRmTlpFJHRva2VuUG9vbGVkKQpkZk5aRSRmb2xsU291bmRWb3dlbEludCA8LSBpbnRlcmFjdGlvbihkZk5aRSRzcGVlY2hfZm9sX3Bvb2xlZCwgZGZOWkUkdG9rZW5Qb29sZWQpCmRmTlpFJHRva2VuUG9vbGVkLm9yZCA8LSBhcy5vcmRlcmVkKGRmTlpFJHRva2VuUG9vbGVkKQpjb250cmFzdHMoZGZOWkUkdG9rZW5Qb29sZWQub3JkKSA8LSAiY29udHIudHJlYXRtZW50IgpkZk5aRSR2b3dlbHNfcG9vbGVkLm9yZCA8LSBhcy5vcmRlcmVkKGRmTlpFJHZvd2Vsc19wb29sZWQpCmNvbnRyYXN0cyhkZk5aRSR2b3dlbHNfcG9vbGVkLm9yZCkgPC0gImNvbnRyLnRyZWF0bWVudCIKZGZOWkUkc2V4Lm9yZCA8LSBhcy5vcmRlcmVkKGRmTlpFJHNleCkKY29udHJhc3RzKGRmTlpFJHNleC5vcmQpIDwtICJjb250ci50cmVhdG1lbnQiCmRmTlpFJHBsYXlpbmdfcHJvZmljaWVuY3kub3JkIDwtIGFzLm9yZGVyZWQoZGZOWkUkcGxheWluZ19wcm9maWNpZW5jeSkKY29udHJhc3RzKGRmTlpFJHBsYXlpbmdfcHJvZmljaWVuY3kub3JkKSA8LSAiY29udHIudHJlYXRtZW50IgpkZk5aRSRzdGFydCA8LSBkZk5aRSRwb2ludHM9PTEKCmRmVG9uZ2FuIDwtIHN1YnNldChkZixkZiRuYXRpdmVfbGc9PSJUb25nYW4iKQpkZlRvbmdhbiR0b2tlblBvb2xlZCA8LSBmYWN0b3IoZGZUb25nYW4kdG9rZW5Qb29sZWQsIGxldmVscyA9IGMoImHLkCIsImEiLCJly5AiLCJlIiwiacuQIiwiaSIsInXLkCIsInUiLCJvy5AiLCJvIiwiQmIyIiwiRjMiLCJCYjMiLCJENCIsIkY0IikpCmRmVG9uZ2FuJHRva2VuUG9vbGVkW2RmVG9uZ2FuJHRva2VuUG9vbGVkID09ICJhy5AiXSA9ICJhIgpkZlRvbmdhbiR0b2tlblBvb2xlZFtkZlRvbmdhbiR0b2tlblBvb2xlZCA9PSAiZcuQIl0gPSAiZSIKZGZUb25nYW4kdG9rZW5Qb29sZWRbZGZUb25nYW4kdG9rZW5Qb29sZWQgPT0gImnLkCJdID0gImkiCmRmVG9uZ2FuJHRva2VuUG9vbGVkW2RmVG9uZ2FuJHRva2VuUG9vbGVkID09ICJ1y5AiXSA9ICJ1IgpkZlRvbmdhbiR0b2tlblBvb2xlZFtkZlRvbmdhbiR0b2tlblBvb2xlZCA9PSAib8uQIl0gPSAibyIKZGZUb25nYW4kdG9rZW5Qb29sZWQgPC0gZmFjdG9yKGRmVG9uZ2FuJHRva2VuUG9vbGVkKQpkZlRvbmdhbiRwbGF5aW5nX3Byb2ZpY2llbmN5IDwtIGFzLmZhY3RvcihkZlRvbmdhbiRwbGF5aW5nX3Byb2ZpY2llbmN5KQpkZlRvbmdhbiRzcGVlY2hfcHJlY19wb29sZWRbaXMubmEoZGZUb25nYW4kc3BlZWNoX3ByZWNfcG9vbGVkKV0gPSAiTlVMTCIKZGZUb25nYW4kc3BlZWNoX2ZvbF9wb29sZWRbaXMubmEoZGZUb25nYW4kc3BlZWNoX2ZvbF9wb29sZWQpXSA9ICJOVUxMIgpkZlRvbmdhbiRzdWJWb3dlbEludCA8LSBpbnRlcmFjdGlvbihkZlRvbmdhbiRzdWJqZWN0LCBkZlRvbmdhbiR0b2tlblBvb2xlZCkKZGZUb25nYW4kcHJlY1NvdW5kVm93ZWxJbnQgPC0gaW50ZXJhY3Rpb24oZGZUb25nYW4kc3BlZWNoX3ByZWNfcG9vbGVkLCBkZlRvbmdhbiR0b2tlblBvb2xlZCkKZGZUb25nYW4kZm9sbFNvdW5kVm93ZWxJbnQgPC0gaW50ZXJhY3Rpb24oZGZUb25nYW4kc3BlZWNoX2ZvbF9wb29sZWQsIGRmVG9uZ2FuJHRva2VuUG9vbGVkKQpkZlRvbmdhbiR0b2tlblBvb2xlZC5vcmQgPC0gYXMub3JkZXJlZChkZlRvbmdhbiR0b2tlblBvb2xlZCkKY29udHJhc3RzKGRmVG9uZ2FuJHRva2VuUG9vbGVkLm9yZCkgPC0gImNvbnRyLnRyZWF0bWVudCIKZGZUb25nYW4kdm93ZWxzX3Bvb2xlZC5vcmQgPC0gYXMub3JkZXJlZChkZlRvbmdhbiR2b3dlbHNfcG9vbGVkKQpjb250cmFzdHMoZGZUb25nYW4kdm93ZWxzX3Bvb2xlZC5vcmQpIDwtICJjb250ci50cmVhdG1lbnQiCmRmVG9uZ2FuJHNleC5vcmQgPC0gYXMub3JkZXJlZChkZlRvbmdhbiRzZXgpCmNvbnRyYXN0cyhkZlRvbmdhbiRzZXgub3JkKSA8LSAiY29udHIudHJlYXRtZW50IgpkZlRvbmdhbiRwbGF5aW5nX3Byb2ZpY2llbmN5Lm9yZCA8LSBhcy5vcmRlcmVkKGRmVG9uZ2FuJHBsYXlpbmdfcHJvZmljaWVuY3kpCmNvbnRyYXN0cyhkZlRvbmdhbiRwbGF5aW5nX3Byb2ZpY2llbmN5Lm9yZCkgPC0gImNvbnRyLnRyZWF0bWVudCIKZGZUb25nYW4kc3RhcnQgPC0gZGZUb25nYW4kcG9pbnRzPT0xCgojICMgaW5zcGVjdCB2b3dlbCB0b2tlbiBudW1iZXJzIGluIGRpZmZlcmVudCBwcmVjZWRpbmcgYW5kIGZvbGxvd2luZyBjb250ZXh0cwojIGNhdCgiXG5kZk5aRSRzcGVlY2hfcHJlY19wb29sZWRcbiIpCiMgdGFibGUoZGZOWkUkc3BlZWNoX3ByZWNfcG9vbGVkKQojIGNhdCgiXG5kZk5aRSRzcGVlY2hfZm9sX3Bvb2xlZFxuIikKIyB0YWJsZShkZk5aRSRzcGVlY2hfZm9sX3Bvb2xlZCkKIyBjYXQoIlxuZGZUb25nYW4kc3BlZWNoX3ByZWNfcG9vbGVkXG4iKQojIHRhYmxlKGRmVG9uZ2FuJHNwZWVjaF9wcmVjX3Bvb2xlZCkKIyBjYXQoIlxuZGZOWkUkc3BlZWNoX2ZvbF9wb29sZWRcbiIpCiMgdGFibGUoZGZUb25nYW4kc3BlZWNoX2ZvbF9wb29sZWQpCgojIG1ha2UgY29waWVzIG9mIGRmTlpFIGFuZCBkZlRvbmdhbgpkYXRfTlpFID0gZGZOWkUKZGF0X1RvbmdhbiA9IGRmVG9uZ2FuCgojIHByZWRpY3QgdmFsdWVzIGZyb20gbW9kZWxzCmRhdF9OWkUkcHJlZGljdGVkX3ZhbHVlcyA9IHByZWRpY3QoTlpFLmdhbS5BUi5Nb2QyKQpkYXRfVG9uZ2FuJHByZWRpY3RlZF92YWx1ZXMgPSBwcmVkaWN0KFRvbmdhbi5nYW0uQVIuTW9kMikKCiMgY3JlYXRlIG5ldyBkYXRhLmZyYW1lcwpOWkVfRkxFRUNFID0gZGF0X05aRVtkYXRfTlpFJHRva2VuUG9vbGVkID09ICJpy5AiICYgZGF0X05aRSRzcGVlY2hfcHJlY19wb29sZWQgPT0gImNvcm9uYWxzIiAmIGRhdF9OWkUkc3BlZWNoX2ZvbF9wb29sZWQgPT0gImNvcm9uYWxzIixdClRvbmdhbl9pID0gZGF0X1RvbmdhbltkYXRfVG9uZ2FuJHRva2VuUG9vbGVkID09ICJpIiAmIGRhdF9Ub25nYW4kc3BlZWNoX3ByZWNfcG9vbGVkID09ICJjb3JvbmFscyIgJiBkYXRfVG9uZ2FuJHNwZWVjaF9mb2xfcG9vbGVkID09ICJjb3JvbmFscyIsXQoKTlpFX0RSRVNTID0gZGF0X05aRVtkYXRfTlpFJHRva2VuUG9vbGVkID09ICJlIiAmIGRhdF9OWkUkc3BlZWNoX3ByZWNfcG9vbGVkID09ICJjb3JvbmFscyIgJiBkYXRfTlpFJHNwZWVjaF9mb2xfcG9vbGVkID09ICJjb3JvbmFscyIsXQpUb25nYW5fZSA9IGRhdF9Ub25nYW5bZGF0X1RvbmdhbiR0b2tlblBvb2xlZCA9PSAiZSIgJiBkYXRfVG9uZ2FuJHNwZWVjaF9wcmVjX3Bvb2xlZCA9PSAiY29yb25hbHMiICYgZGF0X1RvbmdhbiRzcGVlY2hfZm9sX3Bvb2xlZCA9PSAiY29yb25hbHMiLF0KCk5aRV9TVEFSVCA9IGRhdF9OWkVbZGF0X05aRSR0b2tlblBvb2xlZCA9PSAiyZDLkCIgJiBkYXRfTlpFJHNwZWVjaF9wcmVjX3Bvb2xlZCA9PSAiY29yb25hbHMiICYgZGF0X05aRSRzcGVlY2hfZm9sX3Bvb2xlZCA9PSAiY29yb25hbHMiLF0KVG9uZ2FuX2EgPSBkYXRfVG9uZ2FuW2RhdF9Ub25nYW4kdG9rZW5Qb29sZWQgPT0gImEiICYgZGF0X1RvbmdhbiRzcGVlY2hfcHJlY19wb29sZWQgPT0gImNvcm9uYWxzIiAmIGRhdF9Ub25nYW4kc3BlZWNoX2ZvbF9wb29sZWQgPT0gImNvcm9uYWxzIixdCgpOWkVfVEhPVUdIVCA9IGRhdF9OWkVbZGF0X05aRSR0b2tlblBvb2xlZCA9PSAib8uQIiAmIGRhdF9OWkUkc3BlZWNoX3ByZWNfcG9vbGVkID09ICJjb3JvbmFscyIgJiBkYXRfTlpFJHNwZWVjaF9mb2xfcG9vbGVkID09ICJjb3JvbmFscyIsXQpUb25nYW5fbyA9IGRhdF9Ub25nYW5bZGF0X1RvbmdhbiR0b2tlblBvb2xlZCA9PSAibyIgJiBkYXRfVG9uZ2FuJHNwZWVjaF9wcmVjX3Bvb2xlZCA9PSAiY29yb25hbHMiICYgZGF0X1RvbmdhbiRzcGVlY2hfZm9sX3Bvb2xlZCA9PSAiY29yb25hbHMiLF0KCiMgZXN0aW1hdGUgc21vb3RocyB1c2luZyBSJ3MgZ2VuZXJpYyBwcmVkaWN0LnNtb290aC5zcGxpbmUgZnVuY3Rpb24Kc21vb3RoX05aRV9GTEVFQ0U9bGlzdCh0aGV0YT1zZXEobWluKE5aRV9GTEVFQ0UkdGhldGFfdW5jdXRfeikqMTgwL3BpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF4KE5aRV9GTEVFQ0UkdGhldGFfdW5jdXRfeikqMTgwL3BpLCBsZW5ndGg9MTAwKSwgCiAgICAgICAgICAgICAgICAgICAgICAgcj1wcmVkaWN0KHNtb290aC5zcGxpbmUoTlpFX0ZMRUVDRSR0aGV0YV91bmN1dF96LCBOWkVfRkxFRUNFJHByZWRpY3RlZF92YWx1ZXMpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VxKG1pbihOWkVfRkxFRUNFJHRoZXRhX3VuY3V0X3opLCBtYXgoTlpFX0ZMRUVDRSR0aGV0YV91bmN1dF96KSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZW5ndGg9MTAwKSkkeSwgbGluZT1saXN0KGNvbG9yPSJPUkFOR0UwIiwgZGFzaD0iZGFzaCIpKQpzbW9vdGhfVG9uZ2FuX2k9bGlzdCh0aGV0YT1zZXEobWluKFRvbmdhbl9pJHRoZXRhX3VuY3V0X3opKjE4MC9waSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXgoVG9uZ2FuX2kkdGhldGFfdW5jdXRfeikqMTgwL3BpLCBsZW5ndGg9MTAwKSwgCiAgICAgICAgICAgICAgICAgICAgIHI9cHJlZGljdChzbW9vdGguc3BsaW5lKFRvbmdhbl9pJHRoZXRhX3VuY3V0X3osIFRvbmdhbl9pJHByZWRpY3RlZF92YWx1ZXMpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlcShtaW4oVG9uZ2FuX2kkdGhldGFfdW5jdXRfeiksIG1heChUb25nYW5faSR0aGV0YV91bmN1dF96KSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGVuZ3RoPTEwMCkpJHksIGxpbmU9bGlzdChjb2xvcj0iT1JBTkdFMCIsIGRhc2g9IiIpKQoKc21vb3RoX05aRV9EUkVTUz1saXN0KHRoZXRhPXNlcShtaW4oTlpFX0RSRVNTJHRoZXRhX3VuY3V0X3opKjE4MC9waSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1heChOWkVfRFJFU1MkdGhldGFfdW5jdXRfeikqMTgwL3BpLCBsZW5ndGg9MTAwKSwgCiAgICAgICAgICAgICAgICAgICAgICAgcj1wcmVkaWN0KHNtb290aC5zcGxpbmUoTlpFX0RSRVNTJHRoZXRhX3VuY3V0X3osIE5aRV9EUkVTUyRwcmVkaWN0ZWRfdmFsdWVzKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlcShtaW4oTlpFX0RSRVNTJHRoZXRhX3VuY3V0X3opLCBtYXgoTlpFX0RSRVNTJHRoZXRhX3VuY3V0X3opLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxlbmd0aD0xMDApKSR5LCBsaW5lPWxpc3QoY29sb3I9ImRhcmtfYmx1ZSIsIGRhc2g9ImRhc2giKSkKc21vb3RoX1Rvbmdhbl9lPWxpc3QodGhldGE9c2VxKG1pbihUb25nYW5fZSR0aGV0YV91bmN1dF96KSoxODAvcGksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF4KFRvbmdhbl9lJHRoZXRhX3VuY3V0X3opKjE4MC9waSwgbGVuZ3RoPTEwMCksIAogICAgICAgICAgICAgICAgICAgICByPXByZWRpY3Qoc21vb3RoLnNwbGluZShUb25nYW5fZSR0aGV0YV91bmN1dF96LCBUb25nYW5fZSRwcmVkaWN0ZWRfdmFsdWVzKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZXEobWluKFRvbmdhbl9lJHRoZXRhX3VuY3V0X3opLCBtYXgoVG9uZ2FuX2UkdGhldGFfdW5jdXRfeiksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxlbmd0aD0xMDApKSR5LCBsaW5lPWxpc3QoY29sb3I9ImRhcmtfYmx1ZSIsIGRhc2g9IiIpKQoKc21vb3RoX05aRV9TVEFSVD1saXN0KHRoZXRhPXNlcShtaW4oTlpFX1NUQVJUJHRoZXRhX3VuY3V0X3opKjE4MC9waSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1heChOWkVfU1RBUlQkdGhldGFfdW5jdXRfeikqMTgwL3BpLCBsZW5ndGg9MTAwKSwgCiAgICAgICAgICAgICAgICAgICAgICAgcj1wcmVkaWN0KHNtb290aC5zcGxpbmUoTlpFX1NUQVJUJHRoZXRhX3VuY3V0X3osIE5aRV9TVEFSVCRwcmVkaWN0ZWRfdmFsdWVzKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlcShtaW4oTlpFX1NUQVJUJHRoZXRhX3VuY3V0X3opLCBtYXgoTlpFX1NUQVJUJHRoZXRhX3VuY3V0X3opLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxlbmd0aD0xMDApKSR5LCBsaW5lPWxpc3QoY29sb3I9IlJFRDAiLCBkYXNoPSJkYXNoIikpCnNtb290aF9Ub25nYW5fYT1saXN0KHRoZXRhPXNlcShtaW4oVG9uZ2FuX2EkdGhldGFfdW5jdXRfeikqMTgwL3BpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1heChUb25nYW5fYSR0aGV0YV91bmN1dF96KSoxODAvcGksIGxlbmd0aD0xMDApLCAKICAgICAgICAgICAgICAgICAgICAgcj1wcmVkaWN0KHNtb290aC5zcGxpbmUoVG9uZ2FuX2EkdGhldGFfdW5jdXRfeiwgVG9uZ2FuX2EkcHJlZGljdGVkX3ZhbHVlcyksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VxKG1pbihUb25nYW5fYSR0aGV0YV91bmN1dF96KSwgbWF4KFRvbmdhbl9hJHRoZXRhX3VuY3V0X3opLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZW5ndGg9MTAwKSkkeSwgbGluZT1saXN0KGNvbG9yPSJSRUQwIiwgZGFzaD0iIikpCgpzbW9vdGhfTlpFX1RIT1VHSFQ9bGlzdCh0aGV0YT1zZXEobWluKE5aRV9USE9VR0hUJHRoZXRhX3VuY3V0X3opKjE4MC9waSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1heChOWkVfVEhPVUdIVCR0aGV0YV91bmN1dF96KSoxODAvcGksIGxlbmd0aD0xMDApLCAKICAgICAgICAgICAgICAgICAgICAgICByPXByZWRpY3Qoc21vb3RoLnNwbGluZShOWkVfVEhPVUdIVCR0aGV0YV91bmN1dF96LCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBOWkVfVEhPVUdIVCRwcmVkaWN0ZWRfdmFsdWVzKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlcShtaW4oTlpFX1RIT1VHSFQkdGhldGFfdW5jdXRfeiksIG1heChOWkVfVEhPVUdIVCR0aGV0YV91bmN1dF96KSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZW5ndGg9MTAwKSkkeSwgbGluZT1saXN0KGNvbG9yPSJwaW5rIiwgZGFzaD0iZGFzaCIpKQpzbW9vdGhfVG9uZ2FuX289bGlzdCh0aGV0YT1zZXEobWluKFRvbmdhbl9vJHRoZXRhX3VuY3V0X3opKjE4MC9waSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXgoVG9uZ2FuX28kdGhldGFfdW5jdXRfeikqMTgwL3BpLCBsZW5ndGg9MTAwKSwgCiAgICAgICAgICAgICAgICAgICAgIHI9cHJlZGljdChzbW9vdGguc3BsaW5lKFRvbmdhbl9vJHRoZXRhX3VuY3V0X3osIFRvbmdhbl9vJHByZWRpY3RlZF92YWx1ZXMpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlcShtaW4oVG9uZ2FuX28kdGhldGFfdW5jdXRfeiksIG1heChUb25nYW5fbyR0aGV0YV91bmN1dF96KSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGVuZ3RoPTEwMCkpJHksIGxpbmU9bGlzdChjb2xvcj0icGluayIsIGRhc2g9IiIpKQoKIyBzZXQgUmhvIG1heCB0byB0aGUgbWF4IG9mIHRoZSBwcmVkaWN0ZWRfdmFsdWVzICsgNQptYXhfcHJlZGljdGlvbnMgPSBtYXgobWF4KHNtb290aF9OWkVfRkxFRUNFJHIpLCBtYXgoc21vb3RoX05aRV9EUkVTUyRyKSwgbWF4KHNtb290aF9OWkVfU1RBUlQkciksIAogICAgICAgICAgICAgICAgICAgICAgbWF4KHNtb290aF9OWkVfVEhPVUdIVCRyKSwgbWF4KHNtb290aF9Ub25nYW5faSRyKSwgbWF4KHNtb290aF9Ub25nYW5fZSRyKSwgCiAgICAgICAgICAgICAgICAgICAgICBtYXgoc21vb3RoX1Rvbmdhbl9hJHIpLCBtYXgoc21vb3RoX1Rvbmdhbl9vJHIpKQptYXhpbXVtPW1heF9wcmVkaWN0aW9ucys1CnJtKG1heF9wcmVkaWN0aW9ucykKCiMgY29sb3JzIGZyb20gc21vb3RocyBkb24ndCBnZXQgcGFzc2VkIG9uIGNvcnJlY3RseSAtPiBzcGVjaWZ5IGFnYWluCmNvbG9ycyA9IGMoT1JBTkdFMCwgT1JBTkdFMCwgZGFya19ibHVlLCBkYXJrX2JsdWUsIFJFRDAsIFJFRDAsIHBpbmssIHBpbmspCgpwID0gcGxvdF9seSh0eXBlPSdzY2F0dGVycG9sYXInLCBtb2RlPSdsaW5lcycpICU+JSAKICBhZGRfdHJhY2UodGhldGE9c21vb3RoX05aRV9GTEVFQ0UkdGhldGEsIHI9c21vb3RoX05aRV9GTEVFQ0UkciwgbGluZT1saXN0KGNvbG9yPWNvbG9yc1sxXSwgd2lkdGg9Mi41LGRhc2g9c21vb3RoX05aRV9GTEVFQ0UkbGluZSRkYXNoW1sxXV0pLCBuYW1lPSJGTEVFQ0UgL2nLkC8gTlpFIikgJT4lIAogIGFkZF90cmFjZSh0aGV0YT1zbW9vdGhfVG9uZ2FuX2kkdGhldGEsIHI9c21vb3RoX1Rvbmdhbl9pJHIsIGxpbmU9bGlzdChjb2xvcj1jb2xvcnNbMl0sIHdpZHRoPTIuNSwgZGFzaD1zbW9vdGhfVG9uZ2FuX2kkbGluZSRkYXNoW1sxXV0pLCBuYW1lPSIvaS8gVG9uZ2FuIikgJT4lCiAgYWRkX3RyYWNlKHRoZXRhPXNtb290aF9OWkVfRFJFU1MkdGhldGEsIHI9c21vb3RoX05aRV9EUkVTUyRyLCBsaW5lPWxpc3QoY29sb3I9Y29sb3JzWzNdLCB3aWR0aD0yLjUsIGRhc2g9c21vb3RoX05aRV9EUkVTUyRsaW5lJGRhc2hbWzFdXSksIG5hbWU9IkRSRVNTIC9lLyBOWkUiKSAlPiUgCiAgYWRkX3RyYWNlKHRoZXRhPXNtb290aF9Ub25nYW5fZSR0aGV0YSwgcj1zbW9vdGhfVG9uZ2FuX2UkciwgbGluZT1saXN0KGNvbG9yPWNvbG9yc1s0XSwgd2lkdGg9Mi41LCBkYXNoPXNtb290aF9Ub25nYW5fZSRsaW5lJGRhc2hbWzFdXSksIG5hbWU9Ii9lLyBUb25nYW4iKSAlPiUKICBhZGRfdHJhY2UodGhldGE9c21vb3RoX05aRV9TVEFSVCR0aGV0YSwgcj1zbW9vdGhfTlpFX1NUQVJUJHIsIGxpbmU9bGlzdChjb2xvcj1jb2xvcnNbNV0sIHdpZHRoPTIuNSwgZGFzaD1zbW9vdGhfTlpFX1NUQVJUJGxpbmUkZGFzaFtbMV1dKSwgbmFtZT0iU1RBUlQgL2nLkC8gTlpFIikgJT4lIAogIGFkZF90cmFjZSh0aGV0YT1zbW9vdGhfVG9uZ2FuX2EkdGhldGEsIHI9c21vb3RoX1Rvbmdhbl9hJHIsIGxpbmU9bGlzdChjb2xvcj1jb2xvcnNbNl0sIHdpZHRoPTIuNSwgZGFzaD1zbW9vdGhfVG9uZ2FuX2EkbGluZSRkYXNoW1sxXV0pLCBuYW1lPSIvYS8gVG9uZ2FuIikgJT4lCiAgYWRkX3RyYWNlKHRoZXRhPXNtb290aF9OWkVfVEhPVUdIVCR0aGV0YSwgcj1zbW9vdGhfTlpFX1RIT1VHSFQkciwgbGluZT1saXN0KGNvbG9yPWNvbG9yc1s3XSwgd2lkdGg9Mi41LCBkYXNoPXNtb290aF9OWkVfVEhPVUdIVCRsaW5lJGRhc2hbWzFdXSksIG5hbWU9IlRIT1VHSFQgL2/LkC8gTlpFIikgJT4lIAogIGFkZF90cmFjZSh0aGV0YT1zbW9vdGhfVG9uZ2FuX28kdGhldGEsIHI9c21vb3RoX1Rvbmdhbl9vJHIsIGxpbmU9bGlzdChjb2xvcj1jb2xvcnNbOF0sIHdpZHRoPTIuNSwgZGFzaD1zbW9vdGhfVG9uZ2FuX28kbGluZSRkYXNoW1sxXV0pLCBuYW1lPSIvby8gVG9uZ2FuIikgJT4lCiAgbGF5b3V0KHBvbGFyPWxpc3Qoc2VjdG9yPWMoMjAsMTYwKSwgcmFkaWFsYXhpcz1saXN0KGFuZ2xlPTkwLCByYW5nZT1jKDAsbWF4aW11bSkpLCAgCiAgICAgICAgICAgICAgICAgICAgYW5ndWxhcmF4aXM9bGlzdCh0aGV0YXVuaXQ9J3JhZGlhbnMnLCBkaXJlY3Rpb249ImNsb2Nrd2lzZSIsIHJvdGF0aW9uPTApKSwgCiAgICAgICAgIHRpdGxlPSJUb25nYW4gJiBOWkUgJ2NhcmRpbmFsIHZvd2VscycgZmxhbmtlZCBieSBjb3JvbmFsIHNvdW5kcyIsIAogICAgICAgICBsZWdlbmQ9bGlzdChvcmllbnRhdGlvbj0iaCIsIHhhbmNob3I9ImNlbnRlciIsIHg9MC41LHk9MC4wMTIpKQpwCgppZihwcmludFBERj09VFJVRSkKewogIG9yY2EocCwgIkZpZ3VyZTEwLnBkZiIsZm9ybWF0PSJwZGYiKQogIG9yY2EocCwgIkZpZ3VyZTEwLmpwZyIsZm9ybWF0PSJqcGVnIikKfQoKcm0oZGF0X05aRSwgZGF0X1RvbmdhbiwgTlpFX0ZMRUVDRSwgTlpFX0RSRVNTLCBOWkVfU1RBUlQsIE5aRV9USE9VR0hULCBzbW9vdGhfTlpFX0ZMRUVDRSxzbW9vdGhfTlpFX0RSRVNTLCBzbW9vdGhfTlpFX1NUQVJULCBzbW9vdGhfTlpFX1RIT1VHSFQsIHNtb290aF9Ub25nYW5faSwgc21vb3RoX1Rvbmdhbl9lLCBzbW9vdGhfVG9uZ2FuX2EsIHNtb290aF9Ub25nYW5fbywgbWF4aW11bSkKYGBgCgoK